Advertisement
Guest User

Untitled

a guest
Jan 18th, 2019
64
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 120.85 KB | None | 0 0
  1. /* Copyright 2019 Kenneth Brown */
  2.  
  3. /* Licensed under the Apache License, Version 2.0 (the "License"); */
  4. /* you may not use this file except in compliance with the License. */
  5. /* You may obtain a copy of the License at */
  6.  
  7. /*     http://www.apache.org/licenses/LICENSE-2.0 */
  8.  
  9. /* Unless required by applicable law or agreed to in writing, software */
  10. /* distributed under the License is distributed on an "AS IS" BASIS, */
  11. /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
  12. /* See the License for the specific language governing permissions and */
  13. /* limitations under the License. */
  14.  
  15. /*
  16.  
  17.   This product includes software developed by the OpenSSL Project
  18.   for use in the OpenSSL Toolkit (http://www.openssl.org/)
  19. */
  20.  
  21. #include "config.h"
  22. #include <ctype.h>
  23. #include <errno.h>
  24. #include <limits.h>
  25. #include <openssl/crypto.h>
  26. #include <openssl/evp.h>
  27. #include <openssl/hmac.h>
  28. #include <openssl/objects.h>
  29. #include <openssl/rand.h>
  30. #include <openssl/sha.h>
  31. #include <signal.h>
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <sys/stat.h>
  36. #include <sys/types.h>
  37. #include <termios.h>
  38. #include <time.h>
  39. #include <unistd.h>
  40. #include <sys/mman.h>
  41. #include <sys/capability.h>
  42. #include <sys/time.h>
  43. #include <sys/resource.h>
  44.  
  45.  
  46.  
  47. /*Define a size in bytes for the buffers. The entry name and password are handled separately so combined they will make 1024 sized buffers*/
  48. #define BUFFER_SIZES 512
  49.  
  50. //*Define sizes of salts*/
  51. #define EVP2_SALT_SIZE 16
  52. #define EVP1_SALT_SIZE 16
  53. #define HMAC_SALT_SIZE EVP1_SALT_SIZE
  54.  
  55. /*Define block sizes for dbDecrypt and dbEncrypt to use*/
  56. #define EVP_BLOCK_SIZE 1024
  57.  
  58. /*The default PBKDF2 iteration count as per RFC 2889 reccomendation*/
  59. /*The final iteration will differ from this depending on length of user pass and salts generated*/
  60. #define RFC_2889_REC_ITERATIONS 1000
  61.  
  62. /*Default size of password if generation is chosen*/
  63. #define DEFAULT_GENPASS_LENGTH 16
  64.  
  65. /*Naming the structure 'toggle' just makes it easy to remember these are option-toggle variables*/
  66. /*If the value is 1 the option is true/on, if not the option is false/off*/
  67. struct toggleStruct {
  68.     int Add; /*To add a password to a file*/
  69.     int Read; /*To read a password to a file*/
  70.     int Delete; /*To delete an entry from a file*/
  71.     int entryPassArg; /*To enable passing the password from the command line*/
  72.     int dbPassArg; /*To enable passing the password from the command line*/
  73.     int fileGiven; /*To ensure that a file has been specified, program halts if not set to 1*/
  74.     int entryGiven; /*To ensure that an entry has been specified*/
  75.     int updateEntry; /*To specify updating an entry only*/
  76.     int updateEntryPass; /*To secify updating an entry as well as a password*/
  77.     int updateEncPass; /*Update encryption password*/
  78.     int entrySearch; /*Use to find a specific entry instead of operating on all of them*/
  79.     int messageDigest; /*User specified message digest algorithm*/
  80.     int encCipher; /*User specified cipher algorithm*/
  81.     int entryPassLengthGiven; /*Use to specify a length of generated pass*/
  82.     int sendToClipboard; /*Toggle sending entry's password directly to clipboard*/
  83.     int xclipClearTime; /*To use a non-default clear time for the clipboard*/
  84.     int firstRun; /*Keep track if it's the first run*/
  85.     int generateEntryPass; /*Toggle to generate random entry pass*/
  86.     int generateEntryPassAlpha; /*Toggle to generate alphanumeric pass*/
  87.     int allPasses; /*Toggle to read or update allpasses*/
  88. };
  89.  
  90. struct toggleStruct toggle;
  91.  
  92. /*Prototype functions*/
  93.  
  94. /*OpenSSL related functions*/
  95. int primeSSL(); /*Loads EVP cipher and digest objects via name after user species them or parsed from file header*/
  96. int openEnvelope(); /*Opens EVP encrypted envelope file and checks MAC attached*/
  97. void genEvp2Salt(); /*Generates an 8byte random salt to be used by EVP*/
  98. int dbDecrypt(FILE* in, FILE* out); /*OpenSSSL EVP decryption routine*/
  99. int dbEncrypt(FILE* in, FILE* out); /*OpenSSL EVP encryption routine*/
  100. int sealEnvelope(const unsigned char* tmpFileToUse); /*Writes Message data to EVP ecncrypted envelope and attaches MAC*/
  101. void mdList(const OBJ_NAME* obj, void* arg); /*Sets up structure objects needed to list message digests available to OpenSSL*/
  102. void mdLister(); /*Lists the message digests available to OpenSSL*/
  103. void encList(const OBJ_NAME* obj, void* arg); /*Same as mdList but for encryption ciphers*/
  104. void encLister(); /*Same as mdLIster but for encryption ciphers*/
  105. void genEvp1Salt(); /*Generates EVP1 salt*/
  106. void hmacKDF(); /*Derive key for HMAC*/
  107. int evpKDF(unsigned char* dbPass, unsigned char* evpSalt, unsigned int saltLen,const EVP_CIPHER *evpCipher,const EVP_MD *evpDigest, unsigned char *evpKey, unsigned char *evpIv); /*Derive key for EVP ciphers*/
  108. /*Password management functions*/
  109. int writePass(FILE* dbFile); /*Uses EVP1 cipher to write passes to a file*/
  110. int printPasses(FILE* dbFile, unsigned char* searchString); /*Uses EVP1 cipher to read passes from file*/
  111. int deletePass(FILE* dbFile, unsigned char* searchString); /*Uses EVP1 cipher to delete passes from a file*/
  112. int updateEntry(FILE* dbFile, unsigned char* searchString); /*Updates entryName or entryName AND passWord*/
  113. int updateEncPass(FILE* dbFile); /*Update database encryption password*/
  114. /*Password input functions*/
  115. void genPassWord(int stringLength); /*Generates an entry password if 'gen' is specifed*/
  116. unsigned char* getPass(const char* prompt, char* paddedPass); /*Function to retrive passwords with no echo*/
  117. /*Setup functions*/
  118. void allocateBuffers(); /*Allocates all the buffers used*/
  119. int doesFileExist(const unsigned char* filename); /*Checks if the file exists using stat()*/
  120. int returnFileSize(const unsigned char* filename); /*Returns filesize using stat()*/
  121. unsigned char* genFileName(); /*Generates random file names for temporary files*/
  122. /*Cleanup functions*/
  123. void cleanUpFiles(); /*Cleans up temp files*/
  124. void cleanUpBuffers(); /*Writes zeroes to all the buffers we used when done*/
  125. int wipeFile(const unsigned char* filename); /*Wipes temp files used with Schneier 7-Pass method*/
  126. /*Misc functions*/
  127. void signalHandler(int signum); /*Signal handler for Ctrl+C*/
  128. int sendToClipboard(); /*Sends an entry password directly to clipboard*/
  129. int printSyntax(unsigned char* arg); /*Print program usage and help*/
  130. int printMACErrMessage(unsigned char* backupFileName); /*Print MAC error information*/
  131.  
  132. /*OpenSSL variables*/
  133.  
  134. /*These are needed for OpenSSL key ring material*/
  135. /*evpCipher1 will be the first/inner algorithm choosen*/
  136. /*evpCipher2 will be the second/outer algorithm choosen*/
  137. const EVP_CIPHER *evpCipher1, *evpCipher1Old, *evpCipher2;
  138. unsigned char evpKey1[EVP_MAX_KEY_LENGTH], evpKey1Old[EVP_MAX_KEY_LENGTH], evpKey2[EVP_MAX_KEY_LENGTH];
  139. unsigned char evpIv1[EVP_MAX_IV_LENGTH], evpIv1Old[EVP_MAX_KEY_LENGTH], evpIv2[EVP_MAX_IV_LENGTH];
  140. const EVP_MD *evpDigest1 = NULL, *evpDigest2 = NULL;
  141.  
  142. /*These hold the user-supplied password for the database encryption*/
  143. unsigned char* dbPass; /*Will hold the user-supplied database password*/
  144. unsigned char* dbPassStore; /*This stores the dbPass entered by the user to verify it was not mistyped*/
  145. unsigned char* dbPassOld; /*Store old dbPassword for updateEncPass()*/
  146.  
  147. /*EVP cipher and MD name character arrays*/
  148. unsigned char messageDigest1[NAME_MAX], messageDigest2[NAME_MAX]; /*Message digest name to send to EVP functions*/
  149. unsigned char messageDigestStore1[NAME_MAX], messageDigestStore2[NAME_MAX]; /*Stores messageDigest given on commandline*/
  150. unsigned char encCipher1[NAME_MAX], encCipher2[NAME_MAX]; /*Cipher name to send to EVP functions*/
  151. unsigned char encCipherStore1[NAME_MAX], encCipherStore2[NAME_MAX]; /*Stores the encCipher given on commandline*/
  152.  
  153. /*Holds a 64 byte key derived in hmacKDF to be used in HMAC function*/
  154. unsigned char *hmacKey, *hmacKeyNew, *hmacKeyOld;
  155.  
  156. /*Misc crypto variables*/
  157.  
  158. /*Salts*/
  159. unsigned char* evp2Salt; /*This stores the salt to use in EVPBytestoKey for the second/outer algorithm used*/
  160. unsigned char* evp1Salt; /*This stores the salt to use in EVPBytestoKey for the first/inner algorithm used*/
  161. /*Buffers and variables needed for HMAC*/
  162. unsigned char gMac[SHA512_DIGEST_LENGTH]; /*MAC generated from plain-text, thus gMac for generatedMac*/
  163. unsigned char fMac[SHA512_DIGEST_LENGTH]; /*MAC read from file to check against, thus fMac for fileMac*/
  164. unsigned int* gMacLength; /*HMAC() needs an int pointer to put the length of the mac generated into*/
  165.  
  166. /*Character arrays to hold temp file random names*/
  167. unsigned char* tmpFile1;
  168. unsigned char* tmpFile2;
  169. unsigned char* tmpFile3;
  170.  
  171. /*Backup and database file names*/
  172. unsigned char dbFileName[NAME_MAX]; /*Password file name*/
  173. unsigned char backupFileName[NAME_MAX]; /*Buffer to hold the name of backup file for passwords file which will be the same with a .sav suffix*/
  174.  
  175. /*Input buffers*/
  176. unsigned char* entryPass; /*Entry password*/
  177. unsigned char* entryPassStore; /*Buffer to store password for verification checks*/
  178. unsigned char* entryName; /*Entry name*/
  179. unsigned char* entryNameToSearch; /*A buffer with an entry name to search for with updateEntry*/
  180. unsigned char* newEntry; /*A buffer with an entry name to update to with updateEntry*/
  181. unsigned char* newEntryPass; /*A buffer with a password to update an entry's password to with updateEntry*/
  182. unsigned char* newEntryPassStore; /*A buffer to store previous mentioned password for verification*/
  183. unsigned char* paddedPass; /*Holds pointer to buffer for user pass from getPass()*/
  184.  
  185. /*Misc variables*/
  186.  
  187. /*The amount of seconds to wait before clearing the clipboard if we send pass to it with xclip*/
  188. /*This will default to 30 unless the user species -s n to set it to n seconds*/
  189. int xclipClearTime = 30;
  190.  
  191. /*How long an entry password to generate if generation is specifed*/
  192. int entryPassLength;
  193.  
  194. /*To store return values for checking*/
  195. /*Made global in case a function needs to return something else to its caller*/
  196. int returnVal;
  197.  
  198. /*Structs needed to hold termios info when resetting terminal echo'ing after taking password*/
  199. struct termios termisOld, termiosNew;
  200.  
  201. int main(int argc, char* argv[])
  202. {
  203.     /*Print help if no arguments given*/
  204.     if (argc == 1) {
  205.         printSyntax(argv[0]);
  206.         return 1;
  207.     }
  208.    
  209.     /*Check for super user priveleges*/
  210.     if(geteuid() != 0 && getuid() != 0) {
  211.         printf("euid: %i uid: %i\n", geteuid(), getuid());
  212.         printf("No priveleges to lock memory.  You may lose sensitive data to swap! Aborting.\n");
  213.         exit(1);
  214.     } else {
  215.         /*Lock program memory*/
  216.        
  217.         //printf("euid: %i uid: %i\n", geteuid(), getuid());
  218.  
  219.         /*Prevent core dump if program crashes*/
  220.         struct rlimit rl;
  221.  
  222.         rl.rlim_cur = 0;
  223.         rl.rlim_max = 0;
  224.  
  225.         setrlimit(RLIMIT_CORE,&rl);
  226.  
  227.         /*Need variables for libcap functions*/
  228.         cap_t caps;
  229.         cap_value_t cap_list[2];
  230.         cap_value_t clear_list[1];
  231.         caps = cap_get_proc();
  232.         if (caps == NULL) {
  233.             perror("caps");
  234.             exit(1);
  235.         }
  236.         cap_list[0] = CAP_IPC_LOCK;
  237.         clear_list[0] = CAP_SYS_PTRACE;
  238.        
  239.         /*Set CAP_IPC_LOCK so we're not limited to a measely 32K of locked memory*/
  240.         if (cap_set_flag(caps, CAP_EFFECTIVE,1, cap_list, CAP_SET) == -1) {
  241.             perror("caplist CAP_EFFECTIVE");
  242.             exit(1);
  243.         }
  244.         if (cap_set_flag(caps, CAP_INHERITABLE,1, cap_list, CAP_SET) == -1) {
  245.             perror("caplit CAP INHERITABLE");
  246.             exit(1);
  247.         }
  248.         /*Disable ptrace ability*/
  249.         if (cap_set_flag(caps, CAP_EFFECTIVE,1, clear_list, CAP_CLEAR) == -1) {
  250.             perror("clearlist CAP_EFFECTIVE");
  251.             exit(1);
  252.         }
  253.         if (cap_set_flag(caps, CAP_INHERITABLE,1, clear_list, CAP_CLEAR) == -1) {
  254.             perror("clearlist CAP INHERITABLE");
  255.             exit(1);
  256.         }
  257.         if (cap_set_proc(caps) == -1) {
  258.             perror("cap_set_proc");
  259.             exit(1);
  260.         }
  261.         if (cap_free(caps) == -1) {
  262.             perror("cap_free");
  263.             exit(1);
  264.         }
  265.                
  266.         /*Lock all current and future  memory from being swapped*/
  267.         if ( mlockall(MCL_CURRENT|MCL_FUTURE) == -1 ) {
  268.             perror("mlockall");
  269.             exit(1);
  270.         }
  271.        
  272.         /*Drop root*/
  273.         if(geteuid() != 0) { /*If executable was not started as root, but given root privelge through SETUID/SETGID bit*/
  274.             if(setuid(geteuid()) == -1) { /*Drop back to the privelges of the user who executed the binary*/
  275.             perror("setuid");
  276.             exit(1);
  277.             }
  278.             if(getuid() == 0) { /*Fail if we could not drop root priveleges*/
  279.                 printf("Could not drop root\n");
  280.                 exit(1);
  281.             }
  282.         }
  283.     }
  284.  
  285.     /*These calls will ensure that cleanUpFiles and cleanUpBuffers is ran after return call within main*/
  286.  
  287.     atexit(cleanUpFiles);
  288.     atexit(cleanUpBuffers);
  289.  
  290.     allocateBuffers();
  291.  
  292.     signal(SIGINT, signalHandler);
  293.  
  294.     tmpFile1 = genFileName();
  295.     tmpFile2 = genFileName();
  296.     tmpFile3 = genFileName();
  297.  
  298.     /*These file handles refer to temporary and final files in the openEnvelope/sealEnvelope process*/
  299.     /*EVP2EncryptedFile is the second EVP algorithms' cipher-text, which will also represent the final database file without its header*/
  300.     /*EVP2DecryptedFile is the second EVP algorithms' plain-text, i.e. the first EVP algorithms' cipher-text*/
  301.     /*EVP1DataFileTmp is the first EVP algorithms' cipher-text, which will be loaded into buffers for decryption and processing*/
  302.     /*dbFile will contain two salts and crypto information as a header, followed by the second EVP algorithms' cipher-text*/
  303.     FILE *EVP2EncryptedFile, *EVP2DecryptedFile, *EVP1DataFileTmp, *dbFile;
  304.  
  305.     /*This loads up all names of alogirithms for OpenSSL into an object structure so we can call them by name later*/
  306.     /*It is also needed for the mdLIster() and encLister() functions to work*/
  307.     OpenSSL_add_all_algorithms();
  308.  
  309.     int opt; /*for getop()*/
  310.     int errflg = 0; /*Toggle this flag on and off so we can check for errors and act accordingly*/
  311.  
  312.     unsigned i;
  313.  
  314.     unsigned char* token;
  315.  
  316.     /*Process through arguments*/
  317.     while ((opt = getopt(argc, argv, "s:l:f:u:n:d:a:r:p:x:H:c:hUPC")) != -1) {
  318.         switch (opt) {
  319.         case 'h': /*Help*/
  320.             printSyntax("passmanager");
  321.             return 1;
  322.             break;
  323.         case 's':
  324.             if (optarg[0] == '-') {
  325.                 printf("Option -s requires an operand\n");
  326.                 errflg++; /*Set the error flag so program will halt after getopt() is done*/
  327.             }
  328.             xclipClearTime = atoi(optarg);
  329.             toggle.xclipClearTime = 1;
  330.             break;
  331.         case 'l':
  332.             if (optarg[0] == '-') {
  333.                 printf("Option -l requires an operand\n");
  334.                 errflg++; /*Set the error flag so program will halt after getopt() is done*/
  335.             }
  336.             entryPassLength = atoi(optarg);
  337.             if (BUFFER_SIZES < entryPassLength) {
  338.                 entryPassLength = BUFFER_SIZES;
  339.             }
  340.             toggle.entryPassLengthGiven = 1;
  341.             break;
  342.         case 'U': /*Update encryption password*/
  343.             toggle.updateEncPass = 1;
  344.             break;
  345.         case 'C': /*Send entry out to clipboard*/
  346.             toggle.sendToClipboard = 1;
  347.             break;
  348.         case 'P': /*Update entry pasword*/
  349.             toggle.updateEntryPass = 1;
  350.             break;
  351.         case 'a': /*Add password*/
  352.             if (optarg[0] == '-') {
  353.                 printf("Option -a requires an operand\n");
  354.                 errflg++; /*Set the error flag so program will halt after getopt() is done*/
  355.             } else
  356.                 toggle.Add = 1;
  357.             if (strlen(optarg) > BUFFER_SIZES) {
  358.                 printf("\nentry name too long\n");
  359.                 return 1;
  360.             }
  361.             strcpy(entryName, optarg);
  362.             toggle.entryGiven = 1;
  363.             break;
  364.         case 'r': /*Read password(s)*/
  365.             toggle.Read = 1;
  366.             if (optarg[0] == '-') { /*If the first character of optarg is '-' it's another option and not an argument*/
  367.                 printf("Option -r requires an operand\n");
  368.                 errflg++; /*Set the error flag so program will halt after getopt() is done*/
  369.             } else
  370.                 toggle.entrySearch = 1;
  371.             if (strlen(optarg) > BUFFER_SIZES) {
  372.                 printf("\nentry name too long\n");
  373.                 return 1;
  374.             }
  375.             if (strcmp(optarg, "allpasses") == 0)
  376.                 toggle.allPasses = 1;
  377.             strcpy(entryName, optarg);
  378.             toggle.entryGiven = 1;
  379.             break;
  380.         case 'd': /*Delete password*/
  381.             if (optarg[0] == '-') {
  382.                 printf("Option -d requires an operand\n");
  383.                 errflg++; /*Set the error flag so program will halt after getopt() is done*/
  384.             } else
  385.                 toggle.Delete = 1;
  386.             if (strlen(optarg) > BUFFER_SIZES) {
  387.                 printf("\nentry name too long\n");
  388.                 return 1;
  389.             }
  390.             strcpy(entryName, optarg);
  391.             toggle.entryGiven = 1;
  392.             toggle.entrySearch = 1;
  393.             break;
  394.         case 'H': /*Hashing digest for EVPKeytoBytes() to use*/
  395.             if (optarg[0] == '-') {
  396.                 printf("Option -H requires an operand\n");
  397.                 errflg++; /*Set the error flag so program will halt after getopt() is done*/
  398.             }
  399.             if (strcmp(optarg, "list") == 0) {
  400.                 mdLister();
  401.                 return 0;
  402.             }
  403.             toggle.messageDigest = 1;
  404.             token = strtok(optarg, ":");
  405.             if (token == NULL) {
  406.                 printf("Could not parse header.\nIs %s a password file?\n", dbFileName);
  407.                 return 1;
  408.             }
  409.             strcpy(messageDigest1, token);
  410.  
  411.             token = strtok(NULL, ":");
  412.  
  413.             strcpy(messageDigest2, token);
  414.  
  415.             /*Store command-line given parameters for use after messageDigest are read from file header*/
  416.             strcpy(messageDigestStore1, messageDigest1);
  417.             strcpy(messageDigestStore2, messageDigest2);
  418.  
  419.             toggle.messageDigest = 1;
  420.             break;
  421.         case 'c': /*Encryption cipher to use*/
  422.             if (optarg[0] == '-') {
  423.                 printf("Option -c requires an operand\n");
  424.                 errflg++; /*Set the error flag so program will halt after getopt() is done*/
  425.             }
  426.             if (strcmp(optarg, "list") == 0) {
  427.                 encLister();
  428.                 return 0;
  429.             }
  430.             toggle.encCipher = 1;
  431.  
  432.             token = strtok(optarg, ":");
  433.             if (token == NULL) {
  434.                 printf("Could not parse header.\nIs %s a password file?\n", dbFileName);
  435.                 return 1;
  436.             }
  437.             strcpy(encCipher1, token);
  438.  
  439.             token = strtok(NULL, ":");
  440.  
  441.             strcpy(encCipher2, token);
  442.  
  443.             /*Store command-line given parameters for use after encCipher are read from file header*/
  444.             strcpy(encCipherStore1, encCipher1);
  445.             strcpy(encCipherStore2, encCipher2);
  446.  
  447.             toggle.encCipher = 1;
  448.             break;
  449.         case 'f': /*Specify password file*/
  450.             if (toggle.Add == 1) {
  451.                 dbFile = fopen(optarg, "ab");
  452.                 if (dbFile == NULL) /*Make sure the file opens*/
  453.                 {
  454.                     perror(optarg);
  455.                     return errno;
  456.                 }
  457.  
  458.                 /*Grab passworld database filename off the command line*/
  459.                 strcpy(dbFileName, optarg);
  460.             }
  461.             if (toggle.Read == 1) {
  462.                 dbFile = fopen(optarg, "rb");
  463.                 if (dbFile == NULL) /*Make sure the file opens*/
  464.                 {
  465.                     perror(optarg);
  466.                     return errno;
  467.                 }
  468.  
  469.                 strcpy(dbFileName, optarg);
  470.             }
  471.             if (toggle.Delete == 1) {
  472.                 dbFile = fopen(optarg, "rb+");
  473.                 if (dbFile == NULL) /*Make sure the file opens*/
  474.                 {
  475.                     perror(optarg);
  476.                     return errno;
  477.                 }
  478.                 strcpy(dbFileName, optarg);
  479.             }
  480.             if (toggle.updateEncPass == 1) {
  481.                 dbFile = fopen(optarg, "rb+");
  482.                 if (dbFile == NULL) /*Make sure the file opens*/
  483.                 {
  484.                     perror(optarg);
  485.                     return errno;
  486.                 }
  487.                 strcpy(dbFileName, optarg);
  488.             }
  489.             if (toggle.updateEntry == 1) {
  490.                 dbFile = fopen(optarg, "rb+");
  491.                 if (dbFile == NULL) /*Make sure the file opens*/
  492.                 {
  493.                     perror(optarg);
  494.                     return errno;
  495.                 }
  496.                 strcpy(dbFileName, optarg);
  497.             }
  498.             toggle.fileGiven = 1;
  499.             break;
  500.         case 'n': /*Specifies an entry by name*/
  501.             if (optarg[0] == '-') { /*If the first character of optarg is '-' it's another option and not an argument*/
  502.                 printf("Option -n requires an operand\n");
  503.                 errflg++; /*Set the error flag so program will halt after getopt() is done*/
  504.             } else
  505.                 toggle.entrySearch = 1;
  506.             if (strlen(optarg) > BUFFER_SIZES) {
  507.                 printf("\nentry name too long\n");
  508.                 return 1;
  509.             }
  510.             strcpy(entryName, optarg);
  511.             toggle.entryGiven = 1;
  512.             break;
  513.         case 'u': /*Specifies an entry by name*/
  514.             if (optarg[0] == '-') {
  515.                 printf("Option -u requires an operand\n");
  516.                 errflg++; /*Set the error flag so program will halt after getopt() is done*/
  517.             } else
  518.                 toggle.updateEntry = 1;
  519.             if (strlen(optarg) > BUFFER_SIZES) {
  520.                 printf("\nentry name too long\n");
  521.                 return 1;
  522.             }
  523.             if (strcmp(optarg, "allpasses") == 0)
  524.                 toggle.allPasses = 1;
  525.             strcpy(entryNameToSearch, optarg);
  526.             break;
  527.         case 'p': /*If passing entry password from command line*/
  528.             toggle.entryPassArg = 1;
  529.             if (optarg[0] == '-' && strlen(optarg) == 2) {
  530.                 printf("Option -p requires an operand\n");
  531.                 errflg++; /*Set error flag*/
  532.             }
  533.             if (strlen(optarg) > BUFFER_SIZES) {
  534.                 printf("\npassword too long\n");
  535.                 return 1;
  536.             }
  537.             if (strcmp(optarg, "gen") == 0)
  538.                 toggle.generateEntryPass = 1;
  539.             if (strcmp(optarg, "genalpha") == 0)
  540.                 toggle.generateEntryPassAlpha = 1;
  541.             strcpy(entryPass, optarg);
  542.             OPENSSL_cleanse(optarg, strlen(optarg));
  543.             break;
  544.         case 'x': /*If passing database password from command line*/
  545.             toggle.dbPassArg = 1;
  546.             if (optarg[0] == '-' && strlen(optarg) == 2) {
  547.                 errflg++; /*Set error flag*/
  548.                 printf("Option -x requires an operand\n");
  549.             }
  550.             strcpy(dbPass, optarg);
  551.             OPENSSL_cleanse(optarg, strlen(optarg));
  552.             break;
  553.         case ':':
  554.             printf("Option -%c requires an operand\n", optopt);
  555.             errflg++; /*Set error flag*/
  556.             break;
  557.         case '?': /*Get opt error handling, these check that the options were entered in correct syntax but not that the options are right*/
  558.             //u:n:p:x:f:H:c:
  559.             if (optopt == 'f')
  560.                 fprintf(stderr, "Option -%c requires an argument.\n", optopt);
  561.             if (optopt == 'u')
  562.                 fprintf(stderr, "Option -%c requires an argument.\n", optopt);
  563.             if (optopt == 'n')
  564.                 fprintf(stderr, "Option -%c requires an argument.\n", optopt);
  565.             if (optopt == 'd')
  566.                 fprintf(stderr, "Option -%c requires an argument.\n", optopt);
  567.             if (optopt == 'a')
  568.                 fprintf(stderr, "Option -%c requires an argument.\n", optopt);
  569.             if (optopt == 'p')
  570.                 fprintf(stderr, "Option -%c requires an argument.\n", optopt);
  571.             if (optopt == 'x')
  572.                 fprintf(stderr, "Option -%c requires an argument.\n", optopt);
  573.             if (optopt == 'H')
  574.                 fprintf(stderr, "Option -%c requires an argument.\n", optopt);
  575.             if (optopt == 'c')
  576.                 fprintf(stderr, "Option -%c requires an argument.\n", optopt);
  577.             printf("Unrecognized option: -%c\n", optopt);
  578.             errflg++; /*Set error flag*/
  579.         }
  580.     }
  581.  
  582.     /*Sanitize argv and argc of any sensitive information*/
  583.     for (i = 1; i < argc; i++)
  584.         OPENSSL_cleanse(argv[i], strlen(argv[i]));
  585.  
  586.     /*If the user didn't specify a file with -f set error flag on*/
  587.     if (toggle.fileGiven != 1)
  588.         errflg++;
  589.     /*Finally test for errflag and halt program if on*/
  590.     if (errflg) {
  591.         printSyntax("passmanger"); /*Print proper usage of program*/
  592.         return 1;
  593.     }
  594.  
  595.     /*Before anything else, back up the password database*/
  596.     if (returnFileSize(dbFileName) != 0 && toggle.Read != 1) {
  597.         strcpy(backupFileName, dbFileName);
  598.         strcat(backupFileName, ".autobak");
  599.         FILE* backUpFile = fopen(backupFileName, "w");
  600.         if (backUpFile == NULL) {
  601.             printf("Couldn't make a backup file. Be careful...\n");
  602.         } else {
  603.             FILE* copyFile = fopen(dbFileName, "r");
  604.             unsigned char* backUpFileBuffer = calloc(sizeof(unsigned char), returnFileSize(dbFileName));
  605.             returnVal = fread(backUpFileBuffer, sizeof(unsigned char), returnFileSize(dbFileName), copyFile);
  606.             if (returnVal != returnFileSize(dbFileName) / sizeof(unsigned char)) {
  607.                 if (ferror(copyFile)) {
  608.                     printf("Fread failed\n");
  609.                     return 1;
  610.                 }
  611.             }
  612.  
  613.             returnVal = fwrite(backUpFileBuffer, sizeof(unsigned char), returnFileSize(dbFileName), backUpFile);
  614.             if (returnVal != returnFileSize(dbFileName) / sizeof(unsigned char))
  615.                 ;
  616.             {
  617.                 if (ferror(backUpFile)) {
  618.                     printf("fwrite failed @ 485\n");
  619.                     return 1;
  620.                 }
  621.             }
  622.             fclose(copyFile);
  623.             fclose(backUpFile);
  624.             free(backUpFileBuffer);
  625.         }
  626.     }
  627.  
  628.     /*Now the program begins its work*/
  629.  
  630.     /*Test for toggle.Add, toggle.Read, toggle.Delete, toggle.updateEntry or toggle.UpdateEncPass*/
  631.     if (toggle.Add == 1) /*This mode will add an entry*/
  632.     {
  633.  
  634.         /*Check a few things before proceeding*/
  635.  
  636.         /*If dbFile is NULL there was a problem opening it*/
  637.         if (dbFile == NULL) {
  638.             perror(argv[0]); /*Print the error that occured*/
  639.             cleanUpBuffers();
  640.             return errno; /*Return the error's status code*/
  641.         }
  642.  
  643.         /*If generating a random password was specified on command line*/
  644.         if (strcmp(entryPass, "gen") == 0) {
  645.             toggle.generateEntryPass = 1;
  646.             if (toggle.entryPassLengthGiven == 1)
  647.                 genPassWord(entryPassLength);
  648.             else
  649.                 genPassWord(DEFAULT_GENPASS_LENGTH);
  650.         } else if (strcmp(entryPass, "genalpha") == 0) {
  651.             toggle.generateEntryPassAlpha = 1;
  652.             if (toggle.entryPassLengthGiven == 1)
  653.                 genPassWord(entryPassLength);
  654.             else
  655.                 genPassWord(DEFAULT_GENPASS_LENGTH);
  656.         } else if (toggle.entryPassArg != 1) {
  657.             /*Prompt for entry password*/
  658.             getPass("Enter entry password to be saved: ", entryPass);
  659.  
  660.             /*If user entered gen or genalpha at prompt*/
  661.             if (strcmp(entryPass, "gen") == 0) {
  662.                 toggle.generateEntryPass = 1;
  663.                 printf("\nGenerating a random password\n");
  664.                 if (toggle.entryPassLengthGiven == 1)
  665.                     genPassWord(entryPassLength);
  666.                 else
  667.                     genPassWord(DEFAULT_GENPASS_LENGTH);
  668.             } else if (strcmp(entryPass, "genalpha") == 0) {
  669.                 toggle.generateEntryPassAlpha = 1;
  670.                 printf("\nGenerating a random password\n");
  671.                 if (toggle.entryPassLengthGiven == 1)
  672.                     genPassWord(entryPassLength);
  673.                 else
  674.                     genPassWord(DEFAULT_GENPASS_LENGTH);
  675.             } else {
  676.                 /*Verify user gentered password if not gen or genalpha*/
  677.                 getPass("Verify password:", entryPassStore);
  678.                 if (strcmp(entryPass, entryPassStore) != 0) {
  679.                     printf("\nPasswords do not match.  Nothing done.\n\n");
  680.                     cleanUpBuffers();
  681.                     return 1;
  682.                 }
  683.             }
  684.         }
  685.  
  686.         /*Prompt for database password if not supplied as argument*/
  687.         if (toggle.dbPassArg != 1) {
  688.             getPass("Enter database password to encode with: ", dbPass);
  689.  
  690.             /*If this function returns 0 then it is the first time entering the database password so input should be verified*/
  691.             if (returnFileSize(dbFileName) == 0) {
  692.                 getPass("Verify password:", dbPassStore);
  693.                 if (strcmp(dbPass, dbPassStore) != 0) {
  694.                     printf("\nPasswords do not match.  Nothing done.\n\n");
  695.                     cleanUpBuffers();
  696.                     return 1;
  697.                 }
  698.             }
  699.         }
  700.  
  701.         /*Note this will be needed before openEnvelope() is called in all modes except Read*/
  702.         /*Do OpenSSL priming operations*/
  703.         if (primeSSL() != 0) {
  704.             cleanUpBuffers();
  705.             cleanUpFiles();
  706.             return 1;
  707.         }
  708.  
  709.         /*If password file exists run openEnvelope on it*/
  710.         if (returnFileSize(dbFileName) > 0) {
  711.             if (openEnvelope() != 0) {
  712.                 cleanUpBuffers();
  713.                 cleanUpFiles();
  714.                 return 1;
  715.             }
  716.         } else {
  717.             /*Otherwise run these functions to initialize a database*/
  718.             genEvp1Salt();
  719.             genEvp2Salt();
  720.             hmacKDF();
  721.             toggle.firstRun = 1;
  722.         }
  723.  
  724.         /*openEnvelope has decrypted the second EVP algorithm, and placed its plain-text into a tempfile whose randomly-generated name is in a buffer pointed to by tmpFile2*/
  725.  
  726.         /*Open first EVP algorithms' cipher-text for decryption and processing*/
  727.         /*In this case, appending a new entry to it*/
  728.         EVP1DataFileTmp = fopen(tmpFile2, "a+");
  729.         if (EVP1DataFileTmp == NULL) /*Make sure the file opens*/
  730.         {
  731.             perror(argv[0]);
  732.             cleanUpBuffers();
  733.             cleanUpFiles();
  734.             return errno;
  735.         }
  736.         chmod(tmpFile2, S_IRUSR | S_IWUSR);
  737.  
  738.         /*Derives a key for the first EVP algorithm*/
  739.         /*The choosen EVP digest algorithm will be used*/
  740.         /*The salt generated for the first EVP algorithm will also be used*/
  741.         /*The entire KDF will reiterate according to the password length multiplied by the reccomended amount in RFC 2889*/
  742.        
  743.         if(evpKDF(dbPass, evp1Salt, EVP1_SALT_SIZE,evpCipher1,evpDigest1,evpKey1,evpIv1) != 0) {
  744.             return 1;
  745.         }
  746.        
  747.         /*writePass() appends a new entry to EVP1DataFileTmp encrypted with the first EVP algorithm chosen*/
  748.         int writePassResult = writePass(EVP1DataFileTmp);
  749.  
  750.         if (writePassResult == 0) {
  751.             printf("Added \"%s\" to database.\n", entryName);
  752.  
  753.             if (toggle.sendToClipboard == 1) {
  754.                 printf("New password sent to clipboard. Paste with middle-click.\n");
  755.                 sendToClipboard(entryPass);
  756.             }
  757.  
  758.             /*sealEnvelope attaches MAC and encrypts it with OpenSSL*/
  759.             if (sealEnvelope(tmpFile2) != 0) {
  760.                 cleanUpBuffers();
  761.                 cleanUpFiles();
  762.                 return 1;
  763.             }
  764.         }
  765.  
  766.     } else if (toggle.Read == 1) /*Read passwords mode*/
  767.     {
  768.  
  769.         if (toggle.dbPassArg != 1) /*If user did not specify to take pass off command line*/
  770.         {
  771.             getPass("Enter database password: ", dbPass);
  772.         }
  773.  
  774.         EVP2EncryptedFile = fopen(dbFileName, "rb");
  775.         if (EVP2EncryptedFile == NULL) /*Make sure the file opens*/
  776.         {
  777.             perror(argv[0]);
  778.             cleanUpBuffers();
  779.             return errno;
  780.         }
  781.  
  782.         EVP2DecryptedFile = fopen(tmpFile1, "wb");
  783.         if (EVP2DecryptedFile == NULL) /*Make sure the file opens*/
  784.         {
  785.             perror(argv[0]);
  786.             cleanUpBuffers();
  787.             printf("Couldn't open file: %s", tmpFile1);
  788.             return errno;
  789.         }
  790.         chmod(tmpFile1, S_IRUSR | S_IWUSR);
  791.  
  792.         /*Note no primeSSL() needed before openEnvelope() in Read mode*/
  793.         if (openEnvelope() != 0) {
  794.             cleanUpBuffers();
  795.             cleanUpFiles();
  796.             return 1;
  797.         }
  798.  
  799.         /*the file whose name is pointed to by tmpFile2 now contains EVP1 data with no MAC and can be passed to printPasses()*/
  800.         EVP1DataFileTmp = fopen(tmpFile2, "rb");
  801.         if (EVP1DataFileTmp == NULL) {
  802.             perror(argv[0]);
  803.             cleanUpBuffers();
  804.             cleanUpFiles();
  805.             return errno;
  806.         }
  807.         chmod(tmpFile2, S_IRUSR | S_IWUSR);
  808.  
  809.        
  810.         if(evpKDF(dbPass, evp1Salt, EVP1_SALT_SIZE,evpCipher1,evpDigest1,evpKey1,evpIv1) != 0) {
  811.             return 1;
  812.         }
  813.  
  814.         if (toggle.entrySearch == 1 && strcmp(entryName, "allpasses") != 0) /*Find a specific entry to print*/
  815.         {
  816.             printPasses(EVP1DataFileTmp, entryName); /*Decrypt and print pass specified by entryName*/
  817.             if (toggle.sendToClipboard == 1) {
  818.                 printf("Sent password to clipboard. Paste with middle-click.\n");
  819.             }
  820.         } else if (toggle.entrySearch == 1 && strcmp(entryName, "allpasses") == 0)
  821.             printPasses(EVP1DataFileTmp, NULL); /*Decrypt and print all passess*/
  822.  
  823.         fclose(EVP1DataFileTmp);
  824.  
  825.     } else if (toggle.Delete == 1) /*Delete a specified entry*/
  826.     {
  827.  
  828.         if (toggle.dbPassArg != 1) /*If user did not specify to take pass off command line*/
  829.         {
  830.             getPass("Enter database password: ", dbPass);
  831.         }
  832.  
  833.         /*Must specify an entry to delete*/
  834.         if (toggle.entryGiven != 1) /*Fail if no entry specified*/
  835.         {
  836.             fclose(dbFile);
  837.             printf("\nNo entry name was specified\n");
  838.             cleanUpBuffers();
  839.             return 1;
  840.         }
  841.  
  842.         fclose(dbFile);
  843.  
  844.         /*Do OpenSSL priming operations*/
  845.         if (primeSSL()) {
  846.             cleanUpBuffers();
  847.             cleanUpFiles();
  848.             return 1;
  849.         }
  850.  
  851.         if (openEnvelope() != 0) {
  852.             cleanUpBuffers();
  853.             cleanUpFiles();
  854.             return 1;
  855.         }
  856.  
  857.         EVP1DataFileTmp = fopen(tmpFile2, "rb+");
  858.         if (EVP1DataFileTmp == NULL) {
  859.             perror(argv[0]);
  860.             cleanUpBuffers();
  861.             cleanUpFiles();
  862.             return errno;
  863.         }
  864.         chmod(tmpFile2, S_IRUSR | S_IWUSR);
  865.  
  866.        
  867.         if(evpKDF(dbPass, evp1Salt, EVP1_SALT_SIZE,evpCipher1,evpDigest1,evpKey1,evpIv1) != 0) {
  868.             return 1;
  869.         }
  870.  
  871.         /*Delete pass actually works by exclusion*/
  872.         /*It writes all password entries except the one specified to a new temporary file*/
  873.         int deletePassResult = deletePass(EVP1DataFileTmp, entryName);
  874.  
  875.         fclose(EVP1DataFileTmp);
  876.  
  877.         if (deletePassResult == 0) {
  878.  
  879.             /*After the password entry was deleted the rest of the passwords were written to a 3rd temporary file which is encrypted by sealEnvelope*/
  880.             if (sealEnvelope(tmpFile3) != 0) {
  881.                 cleanUpBuffers();
  882.                 cleanUpFiles();
  883.             }
  884.         }
  885.     } else if (toggle.updateEntry == 1) /*Update an entry name*/
  886.     {
  887.  
  888.         if (toggle.dbPassArg != 1) /*If user did not specify to take pass off command line*/
  889.         {
  890.             getPass("Enter database password: ", dbPass);
  891.         }
  892.  
  893.         /*Get new entry*/
  894.         if (toggle.entryGiven == 1) {
  895.             strcpy(newEntry, entryName);
  896.         } else {
  897.             /*If no new entry was specified then just update the password*/
  898.             strcpy(newEntry, entryNameToSearch);
  899.             toggle.updateEntryPass = 1;
  900.         }
  901.  
  902.         /*If entry password to update to was supplied by command line argument*/
  903.         if (toggle.entryPassArg == 1)
  904.             toggle.updateEntryPass = 1;
  905.  
  906.         /*Get new pass*/
  907.         if (toggle.updateEntryPass) {
  908.             /*If entryPass supplied by command line, and generated randomly if it is 'gen'*/
  909.             if (strcmp(entryPass, "gen") == 0) {
  910.                 if (toggle.entryPassLengthGiven == 1) {
  911.                     toggle.generateEntryPass = 1;
  912.                     genPassWord(entryPassLength);
  913.                     /*Have to copy over passWord to newEntryPass since genPassWord() operates on entryPass buffer*/
  914.                     strcpy(newEntryPass, entryPass);
  915.                 } else {
  916.                     genPassWord(DEFAULT_GENPASS_LENGTH);
  917.                     strcpy(newEntryPass, entryPass);
  918.                 }
  919.             } else if (strcmp(entryPass, "genalpha") == 0) {
  920.                 toggle.generateEntryPassAlpha = 1;
  921.                 if (toggle.entryPassLengthGiven == 1) {
  922.                     genPassWord(entryPassLength);
  923.                     /*Have to copy over passWord to newEntryPass since genPassWord() operates on entryPass buffer*/
  924.                     strcpy(newEntryPass, entryPass);
  925.                 } else {
  926.                     genPassWord(DEFAULT_GENPASS_LENGTH);
  927.                     strcpy(newEntryPass, entryPass);
  928.                 }
  929.             } else if (toggle.entryPassArg != 1) /*entryPass was not supplied via command line*/
  930.             {
  931.                 /*Prompt for pass via user input instead*/
  932.                 getPass("Enter entry password to be saved: ", newEntryPass);
  933.  
  934.                 /*If password retrieved by prompt was gen/genalpha generate a random password*/
  935.                 if (strcmp(newEntryPass, "gen") == 0) {
  936.                     toggle.generateEntryPass = 1;
  937.                     printf("\nGenerating a random password\n");
  938.                     if (toggle.entryPassLengthGiven == 1) {
  939.                         genPassWord(entryPassLength);
  940.                         /*Have to copy over entryPass to newEntryPass since genPassWord() operates on entryPass buffer*/
  941.                         strcpy(newEntryPass, entryPass);
  942.                     } else {
  943.                         genPassWord(DEFAULT_GENPASS_LENGTH);
  944.                         strcpy(newEntryPass, entryPass);
  945.                     }
  946.                 } else if (strcmp(newEntryPass, "genalpha") == 0) {
  947.                     toggle.generateEntryPassAlpha = 1;
  948.                     printf("\nGenerating a random password\n");
  949.                     if (toggle.entryPassLengthGiven == 1) {
  950.                         genPassWord(entryPassLength);
  951.                         /*Have to copy over entryPass to newEntryPass since genPassWord() operates on entryPass buffer*/
  952.                         strcpy(newEntryPass, entryPass);
  953.                     } else {
  954.                         genPassWord(DEFAULT_GENPASS_LENGTH);
  955.                         strcpy(newEntryPass, entryPass);
  956.                     }
  957.                 } else {
  958.                     /*If retrieved password was not gen/genalpha verify it was not mistyped*/
  959.                     getPass("Veryify password:", newEntryPassStore);
  960.                     if (strcmp(newEntryPass, newEntryPassStore) != 0) {
  961.                         printf("\nPasswords do not match.  Nothing done.\n\n");
  962.                         cleanUpBuffers();
  963.                         return 1;
  964.                     }
  965.                 }
  966.             } else if (toggle.entryPassArg == 1) /*This condition is true if the user DID supply a password but it isn't 'gen'*/
  967.             {
  968.                 strcpy(newEntryPass, entryPass);
  969.             }
  970.         }
  971.  
  972.         fclose(dbFile);
  973.  
  974.         /*Do OpenSSL priming operations*/
  975.         if (primeSSL() != 0) {
  976.             cleanUpBuffers();
  977.             cleanUpFiles();
  978.             return 1;
  979.         }
  980.  
  981.         if (openEnvelope() != 0) {
  982.             cleanUpBuffers();
  983.             cleanUpFiles();
  984.             return 1;
  985.         }
  986.  
  987.         EVP1DataFileTmp = fopen(tmpFile2, "rb+");
  988.         if (EVP1DataFileTmp == NULL) {
  989.             perror(argv[0]);
  990.             cleanUpBuffers();
  991.             cleanUpFiles();
  992.             return errno;
  993.         }
  994.         chmod(tmpFile2, S_IRUSR | S_IWUSR);
  995.        
  996.         if(evpKDF(dbPass, evp1Salt, EVP1_SALT_SIZE,evpCipher1,evpDigest1,evpKey1,evpIv1) != 0) {
  997.             return 1;
  998.         }
  999.  
  1000.         /*Works like deletePass() but instead of excluding matched entry, modfies its buffer values and then outputs to 3rd temp file*/
  1001.         int updateEntryResult = updateEntry(EVP1DataFileTmp, entryNameToSearch);
  1002.  
  1003.         fclose(EVP1DataFileTmp);
  1004.  
  1005.         if (updateEntryResult == 0) {
  1006.             if (toggle.sendToClipboard == 1) {
  1007.                 printf("Sent new password to clipboard. Paste with middle-click.\n");
  1008.                 sendToClipboard(entryPass);
  1009.             }
  1010.  
  1011.             if (sealEnvelope(tmpFile3) != 0) {
  1012.                 cleanUpBuffers();
  1013.                 cleanUpFiles();
  1014.             }
  1015.         }
  1016.     } else if (toggle.updateEncPass == 1) /*Update the database encryption password*/
  1017.     {
  1018.         fclose(dbFile);
  1019.  
  1020.         if (toggle.dbPassArg != 1) /*If user did not specify to take pass off command line*/
  1021.         {
  1022.             getPass("Enter current database password: ", dbPass);
  1023.         }
  1024.  
  1025.         if (openEnvelope(encCipher2, messageDigest2, dbPass) != 0) {
  1026.             cleanUpBuffers();
  1027.             cleanUpFiles();
  1028.             return 1;
  1029.         }
  1030.  
  1031.         EVP1DataFileTmp = fopen(tmpFile2, "rb+");
  1032.         if (EVP1DataFileTmp == NULL) {
  1033.             perror(argv[0]);
  1034.             cleanUpBuffers();
  1035.             cleanUpFiles();
  1036.             return errno;
  1037.         }
  1038.         chmod(tmpFile2, S_IRUSR | S_IWUSR);
  1039.  
  1040.         /*Must store old evp1 key data to decrypt database before new key material is generated*/
  1041.         strcpy(dbPassOld, dbPass);
  1042.         memcpy(hmacKeyOld, hmacKey, sizeof(unsigned char) * SHA512_DIGEST_LENGTH);
  1043.  
  1044.         /*If -U was given but neither -c or -H*/
  1045.         if (toggle.updateEncPass == 1 && (toggle.encCipher != 1 && toggle.messageDigest != 1)) {
  1046.             /*Get new encryption password from user*/
  1047.             getPass("Enter new database password: ", dbPass);
  1048.  
  1049.             getPass("Verify password:", dbPassStore);
  1050.             if (strcmp(dbPass, dbPassStore) != 0) {
  1051.                 printf("Passwords don't match, not changing.\n");
  1052.                 /*If not changing, replace old dbPass back into dbPass*/
  1053.                 strcpy(dbPass, dbPassOld);
  1054.                 cleanUpBuffers();
  1055.                 cleanUpFiles();
  1056.                 return 1;
  1057.             } else {
  1058.                 printf("Changed password.\n");
  1059.                 hmacKDF();
  1060.                 memcpy(hmacKeyNew, hmacKey, sizeof(unsigned char) * SHA512_DIGEST_LENGTH);
  1061.             }
  1062.  
  1063.             /*Change cipher and digest if specified*/
  1064.             if (toggle.encCipher == 1) {
  1065.                 strcpy(encCipher1, encCipherStore1);
  1066.                 strcpy(encCipher2, encCipherStore2);
  1067.                 printf("Changing cipher to %s:%s\n", encCipherStore1, encCipherStore2);
  1068.             }
  1069.             if (toggle.messageDigest == 1) {
  1070.                 strcpy(messageDigest1, messageDigestStore2);
  1071.                 strcpy(messageDigest2, messageDigestStore2);
  1072.                 printf("Changing digest to %s\n", messageDigestStore2);
  1073.             }
  1074.         }
  1075.         /*-U was given but not -P and -c and/or -H might be there*/
  1076.         else if (toggle.updateEncPass == 1 && toggle.updateEntryPass != 1) {
  1077.             if (toggle.encCipher == 1) {
  1078.                 strcpy(encCipher1, encCipherStore1);
  1079.                 strcpy(encCipher2, encCipherStore2);
  1080.                 printf("Changing cipher to %s:%s\n", encCipherStore1, encCipherStore2);
  1081.             }
  1082.             if (toggle.messageDigest == 1) {
  1083.                 strcpy(messageDigest1, messageDigestStore1);
  1084.                 strcpy(messageDigest2, messageDigestStore2);
  1085.                 printf("Changing digest to %s:%s\n", messageDigestStore1, messageDigestStore2);
  1086.             }
  1087.             memcpy(hmacKeyNew, hmacKey, sizeof(unsigned char) * SHA512_DIGEST_LENGTH);
  1088.         }
  1089.         /*If -P is given along with -c or -H*/
  1090.         else {
  1091.             /*Get new encryption password from user*/
  1092.             getPass("Enter new database password: ", dbPass);
  1093.  
  1094.             getPass("Verify password:", dbPassStore);
  1095.             if (strcmp(dbPass, dbPassStore) != 0) {
  1096.                 printf("Passwords don't match, not changing.\n");
  1097.                 strcpy(dbPass, dbPassOld);
  1098.                 cleanUpBuffers();
  1099.                 cleanUpFiles();
  1100.                 return 1;
  1101.             } else {
  1102.                 printf("Changed password.\n");
  1103.                 hmacKDF();
  1104.                 memcpy(hmacKeyNew, hmacKey, sizeof(unsigned char) * SHA512_DIGEST_LENGTH);
  1105.             }
  1106.  
  1107.             /*Change crypto settings*/
  1108.             if (toggle.encCipher == 1) {
  1109.                 strcpy(encCipher1, encCipherStore1);
  1110.                 strcpy(encCipher2, encCipherStore2);
  1111.                 printf("Changing cipher to %s:%s\n", encCipherStore1, encCipherStore2);
  1112.             }
  1113.             if (toggle.messageDigest == 1) {
  1114.                 strcpy(messageDigest1, messageDigestStore1);
  1115.                 strcpy(messageDigest2, messageDigestStore2);
  1116.                 printf("Changing digest to %s:%s\n", messageDigestStore1, messageDigestStore2);
  1117.             }
  1118.         }
  1119.  
  1120.         /*Do OpenSSL priming operations*/
  1121.         /*This will change to the cipher just specified*/
  1122.         if (primeSSL() != 0) {
  1123.             cleanUpBuffers();
  1124.             cleanUpFiles();
  1125.             return 1;
  1126.         }
  1127.  
  1128.         /*The updateEncPass function simply decrypts with the old key and cipher settings and re-encrypts with new key and/or cipher settings*/
  1129.         int updateEncPassResult = updateEncPass(EVP1DataFileTmp);
  1130.  
  1131.         fclose(EVP1DataFileTmp);
  1132.  
  1133.         if (updateEncPassResult == 0) {
  1134.             if (sealEnvelope(tmpFile3) != 0) {
  1135.                 cleanUpBuffers();
  1136.                 cleanUpFiles();
  1137.                 return 1;
  1138.             }
  1139.         }
  1140.  
  1141.     } else {
  1142.         printSyntax("passmanager"); /*Just in case something else happens...*/
  1143.         return 1;
  1144.     }
  1145.  
  1146.     cleanUpBuffers();
  1147.     cleanUpFiles();
  1148.     return 0;
  1149. }
  1150.  
  1151. int printPasses(FILE* dbFile, unsigned char* searchString)
  1152. {
  1153.     unsigned i, ii;
  1154.     int entriesMatched = 0;
  1155.  
  1156.     int outlen, tmplen;
  1157.     EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
  1158.     EVP_CIPHER_CTX_init(ctx);
  1159.  
  1160.     /*Get the filesize*/
  1161.     long fileSize;
  1162.     fseek(dbFile, 0L, SEEK_END);
  1163.     fileSize = ftell(dbFile);
  1164.     fseek(dbFile, 0L, SEEK_SET);
  1165.  
  1166.     unsigned char* entryBuffer = calloc(sizeof(unsigned char), BUFFER_SIZES);
  1167.     unsigned char* passBuffer = calloc(sizeof(unsigned char), BUFFER_SIZES);
  1168.     unsigned char* encryptedBuffer = calloc(sizeof(unsigned char), fileSize);
  1169.     unsigned char* decryptedBuffer = calloc(sizeof(unsigned char), fileSize + EVP_MAX_BLOCK_LENGTH);
  1170.  
  1171.     /*Read the file into a buffer and check for error*/
  1172.     returnVal = fread(encryptedBuffer, sizeof(unsigned char), fileSize, dbFile);
  1173.     if (returnVal != fileSize / sizeof(unsigned char)) {
  1174.         if (ferror(dbFile)) {
  1175.             printf("Fread failed in printPasses\n");
  1176.             return 1;
  1177.         }
  1178.     }
  1179.  
  1180.     /*This will be the gMac, as in generated MAC*/
  1181.     HMAC(EVP_sha512(), hmacKey, SHA512_DIGEST_LENGTH, encryptedBuffer, fileSize, gMac, gMacLength);
  1182.  
  1183.     /*Check if the MAC from the EVP2DecryptedFile matches MAC generated via HMAC*/
  1184.     /*Return error status before proceeding and clean up sensitive data*/
  1185.     if (memcmp(fMac, gMac, SHA512_DIGEST_LENGTH) != 0) {
  1186.         printMACErrMessage(backupFileName);
  1187.  
  1188.         free(entryBuffer);
  1189.         free(passBuffer);
  1190.         free(encryptedBuffer);
  1191.         free(decryptedBuffer);
  1192.         cleanUpFiles();
  1193.         cleanUpBuffers();
  1194.         return 1;
  1195.     }
  1196.  
  1197.     EVP_DecryptInit(ctx, evpCipher1, evpKey1, evpIv1);
  1198.  
  1199.     if (!EVP_DecryptUpdate(ctx, decryptedBuffer, &outlen, encryptedBuffer, fileSize)) {
  1200.         /* Error */
  1201.         EVP_CIPHER_CTX_cleanup(ctx);
  1202.         OPENSSL_cleanse(decryptedBuffer, sizeof(unsigned char) * fileSize + EVP_MAX_BLOCK_LENGTH);
  1203.         free(entryBuffer);
  1204.         free(passBuffer);
  1205.         free(encryptedBuffer);
  1206.         free(decryptedBuffer);
  1207.         free(ctx);
  1208.  
  1209.         cleanUpFiles();
  1210.         cleanUpBuffers();
  1211.         return 1;
  1212.     }
  1213.     /* Buffer passed to EVP_EncryptFinal() must be after data just
  1214.             * encrypted to avoid overwriting it.
  1215.             */
  1216.  
  1217.     if (!EVP_DecryptFinal_ex(ctx, decryptedBuffer + outlen, &tmplen)) {
  1218.         /* Error */
  1219.         EVP_CIPHER_CTX_cleanup(ctx);
  1220.         OPENSSL_cleanse(decryptedBuffer, sizeof(unsigned char) * fileSize + EVP_MAX_BLOCK_LENGTH);
  1221.         free(entryBuffer);
  1222.         free(passBuffer);
  1223.         free(encryptedBuffer);
  1224.         free(decryptedBuffer);
  1225.         free(ctx);
  1226.  
  1227.         cleanUpFiles();
  1228.         cleanUpBuffers();
  1229.         return 1;
  1230.     }
  1231.     outlen += tmplen;
  1232.     EVP_CIPHER_CTX_cleanup(ctx);
  1233.  
  1234.     /*Loop to process the file.*/
  1235.     for (ii = 0; ii < outlen; ii += (BUFFER_SIZES * 2)) {
  1236.  
  1237.         /*Copy the decrypted information into entryBuffer and passBuffer*/
  1238.         for (i = 0; i < BUFFER_SIZES; i++) {
  1239.             entryBuffer[i] = decryptedBuffer[i + ii];
  1240.             passBuffer[i] = decryptedBuffer[i + ii + BUFFER_SIZES];
  1241.         }
  1242.  
  1243.         if (searchString != NULL) /*If an entry name was specified*/
  1244.         {
  1245.             /*Use strncmp and search the first n elements of entryBuffer, where n is the length of the search string*/
  1246.             /*This will allow the search of partial matches, or an exact match to be printed*/
  1247.             if (strncmp(searchString, entryBuffer, strlen(searchString)) == 0) {
  1248.                 if (toggle.sendToClipboard == 1) {
  1249.                     printf("%s\n", entryBuffer);
  1250.                     sendToClipboard(passBuffer);
  1251.                 } else {
  1252.                     printf("%s : %s\n", entryBuffer, passBuffer);
  1253.                 }
  1254.                 entriesMatched++;
  1255.             }
  1256.         } else /*If an entry name wasn't specified, print them all*/
  1257.             printf("%s : %s\n", entryBuffer, passBuffer);
  1258.     }
  1259.  
  1260.     if (entriesMatched == 0 && searchString != NULL)
  1261.         printf("Nothing matched \"%s\"\n", searchString);
  1262.  
  1263.     OPENSSL_cleanse(entryBuffer, sizeof(unsigned char) * BUFFER_SIZES);
  1264.     OPENSSL_cleanse(passBuffer, sizeof(unsigned char) * BUFFER_SIZES);
  1265.     OPENSSL_cleanse(decryptedBuffer, sizeof(unsigned char) * fileSize + EVP_MAX_BLOCK_LENGTH);
  1266.  
  1267.     free(entryBuffer);
  1268.     free(passBuffer);
  1269.     free(encryptedBuffer);
  1270.     free(decryptedBuffer);
  1271.     free(ctx);
  1272.  
  1273.     return 0;
  1274. }
  1275.  
  1276. int updateEntry(FILE* dbFile, unsigned char* searchString)
  1277. {
  1278.     unsigned i, ii = 0;
  1279.     int lastCheck = 0;
  1280.     int noEntryMatched = 1;
  1281.  
  1282.     int outlen, tmplen;
  1283.  
  1284.     int numberOfSymbols = 0;
  1285.  
  1286.     unsigned char* fileBuffer;
  1287.  
  1288.     FILE* tmpFile;
  1289.  
  1290.     unsigned char* entryBuffer = calloc(sizeof(unsigned char), BUFFER_SIZES);
  1291.     unsigned char* passBuffer = calloc(sizeof(unsigned char), BUFFER_SIZES);
  1292.  
  1293.     /*Get the filesize*/
  1294.     long fileSize;
  1295.     fseek(dbFile, 0L, SEEK_END);
  1296.     fileSize = ftell(dbFile);
  1297.     fseek(dbFile, 0L, SEEK_SET);
  1298.  
  1299.     unsigned char* encryptedBuffer = calloc(sizeof(unsigned char), fileSize + EVP_MAX_BLOCK_LENGTH);
  1300.     unsigned char* decryptedBuffer = calloc(sizeof(unsigned char), fileSize + EVP_MAX_BLOCK_LENGTH);
  1301.  
  1302.     returnVal = fread(encryptedBuffer, sizeof(unsigned char), fileSize, dbFile);
  1303.     if (returnVal != fileSize / sizeof(unsigned char)) {
  1304.         if (ferror(dbFile)) {
  1305.             printf("Fread failed in updatePass()\n");
  1306.             return 1;
  1307.         }
  1308.     }
  1309.  
  1310.     /*This will be the gMac as in generated MAC*/
  1311.     HMAC(EVP_sha512(), hmacKey, SHA512_DIGEST_LENGTH, encryptedBuffer, fileSize, gMac, gMacLength);
  1312.  
  1313.     /*Check if the MAC from the EVP2DecryptedFile matches MAC generated via HMAC*/
  1314.  
  1315.     /*Return error status before proceeding and clean up sensitive data*/
  1316.     if (memcmp(fMac, gMac, SHA512_DIGEST_LENGTH) != 0) {
  1317.         printMACErrMessage(backupFileName);
  1318.  
  1319.         free(entryBuffer);
  1320.         free(passBuffer);
  1321.         free(encryptedBuffer);
  1322.         free(decryptedBuffer);
  1323.  
  1324.         cleanUpFiles();
  1325.         cleanUpBuffers();
  1326.         return 1;
  1327.     }
  1328.  
  1329.     EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
  1330.     EVP_CIPHER_CTX_init(ctx);
  1331.  
  1332.     fileBuffer = calloc(sizeof(unsigned char), fileSize);
  1333.  
  1334.     EVP_DecryptInit(ctx, evpCipher1, evpKey1, evpIv1);
  1335.  
  1336.     /*Decrypt file and store into decryptedBuffer*/
  1337.     if (!EVP_DecryptUpdate(ctx, decryptedBuffer, &outlen, encryptedBuffer, fileSize)) {
  1338.         /* Error */
  1339.         EVP_CIPHER_CTX_cleanup(ctx);
  1340.         OPENSSL_cleanse(decryptedBuffer, sizeof(unsigned char) * fileSize + EVP_MAX_BLOCK_LENGTH);
  1341.         free(entryBuffer);
  1342.         free(passBuffer);
  1343.         free(encryptedBuffer);
  1344.         free(decryptedBuffer);
  1345.         free(fileBuffer);
  1346.         free(ctx);
  1347.  
  1348.         cleanUpFiles();
  1349.         cleanUpBuffers();
  1350.         return 1;
  1351.     }
  1352.     /* Buffer passed to EVP_EncryptFinal() must be after data just
  1353.             * encrypted to avoid overwriting it.
  1354.             */
  1355.  
  1356.     if (!EVP_DecryptFinal_ex(ctx, decryptedBuffer + outlen, &tmplen)) {
  1357.         /* Error */
  1358.         EVP_CIPHER_CTX_cleanup(ctx);
  1359.         OPENSSL_cleanse(decryptedBuffer, sizeof(unsigned char) * fileSize + EVP_MAX_BLOCK_LENGTH);
  1360.         free(entryBuffer);
  1361.         free(passBuffer);
  1362.         free(encryptedBuffer);
  1363.         free(decryptedBuffer);
  1364.         free(fileBuffer);
  1365.         free(ctx);
  1366.  
  1367.         cleanUpFiles();
  1368.         cleanUpBuffers();
  1369.         return 1;
  1370.     }
  1371.     outlen += tmplen;
  1372.     EVP_CIPHER_CTX_cleanup(ctx);
  1373.  
  1374.     for (ii = 0; ii < outlen; ii += (BUFFER_SIZES * 2)) {
  1375.  
  1376.         for (i = 0; i < BUFFER_SIZES; i++) {
  1377.             entryBuffer[i] = decryptedBuffer[i + ii];
  1378.             passBuffer[i] = decryptedBuffer[i + ii + BUFFER_SIZES];
  1379.         }
  1380.  
  1381.         /*If an entry matched searchString or allpasses was specified*/
  1382.         if ((lastCheck = strncmp(searchString, entryBuffer, strlen(searchString))) == 0 || toggle.allPasses == 1) {
  1383.  
  1384.             /*A clunky boolean to test if any entries were matched*/
  1385.             noEntryMatched = 0;
  1386.  
  1387.             //Update content in entryName before encrypting back
  1388.             if (toggle.entryGiven == 1) {
  1389.                 memcpy(entryBuffer, newEntry, BUFFER_SIZES);
  1390.             }
  1391.  
  1392.             /*This will preserve the alphanumeric nature of a password if it has no symbols*/
  1393.             if (toggle.allPasses == 1) {
  1394.                 for (i = 0; i < strlen(passBuffer); i++) {
  1395.                     if (isupper(passBuffer[i]) == 0 && islower(passBuffer[i]) == 0 && isdigit(passBuffer[i]) == 0)
  1396.                         numberOfSymbols++;
  1397.                 }
  1398.  
  1399.                 if (numberOfSymbols == 0) {
  1400.                     toggle.generateEntryPassAlpha = 1;
  1401.                     toggle.generateEntryPass = 0;
  1402.                 } else {
  1403.                     toggle.generateEntryPassAlpha = 0;
  1404.                     toggle.generateEntryPass = 1;
  1405.                 }
  1406.                 numberOfSymbols = 0;
  1407.             }
  1408.  
  1409.             /*Generate random passwords if gen was given, and for all if allpasses was given*/
  1410.             /*If allpasses was given, they will be random regardless if gen is not set.*/
  1411.             if (toggle.updateEntryPass == 1 && (toggle.generateEntryPass == 1 || toggle.allPasses == 1)) {
  1412.  
  1413.                 /*This way we can generate a new pass for each entry during a bulk update*/
  1414.                 if (toggle.entryPassLengthGiven == 1) {
  1415.                     genPassWord(entryPassLength);
  1416.                     /*Have to copy over entryPass to newEntryPass since genPassWord() operates on entryPass buffer*/
  1417.                     strcpy(newEntryPass, entryPass);
  1418.                 } else {
  1419.                     genPassWord(DEFAULT_GENPASS_LENGTH);
  1420.                     strcpy(newEntryPass, entryPass);
  1421.                 }
  1422.                 memcpy(passBuffer, newEntryPass, BUFFER_SIZES);
  1423.                 /*Do the same as above but if an alphanumeric pass was specified*/
  1424.             } else if (toggle.updateEntryPass == 1 && (toggle.generateEntryPassAlpha == 1 || toggle.allPasses == 1)) {
  1425.                 if (toggle.entryPassLengthGiven == 1) {
  1426.                     genPassWord(entryPassLength);
  1427.                     strcpy(newEntryPass, entryPass);
  1428.                 } else {
  1429.                     genPassWord(DEFAULT_GENPASS_LENGTH);
  1430.                     strcpy(newEntryPass, entryPass);
  1431.                 }
  1432.                 memcpy(passBuffer, newEntryPass, BUFFER_SIZES);
  1433.             }
  1434.  
  1435.             if (toggle.updateEntryPass == 1)
  1436.                 memcpy(passBuffer, newEntryPass, BUFFER_SIZES);
  1437.  
  1438.             /*Copy the entryBuffer and passBuffer out to fileBuffer*/
  1439.             for (i = 0; i < BUFFER_SIZES * 2; i++) {
  1440.                 if (i < BUFFER_SIZES)
  1441.                     fileBuffer[ii + i] = entryBuffer[i];
  1442.                 else
  1443.                     fileBuffer[(ii + BUFFER_SIZES) + (i - BUFFER_SIZES)] = passBuffer[i - BUFFER_SIZES];
  1444.             }
  1445.             if (toggle.entryGiven == 1)
  1446.                 printf("Updating \"%s\" to \"%s\" ...\n", searchString, entryBuffer);
  1447.             else
  1448.                 printf("Matched \"%s\" to \"%s\" (Updating...)\n", searchString, entryBuffer);
  1449.         } else { /*Write back the original entry and pass if nothing matched searchString*/
  1450.             for (i = 0; i < BUFFER_SIZES * 2; i++) {
  1451.                 if (i < BUFFER_SIZES)
  1452.                     fileBuffer[ii + i] = entryBuffer[i];
  1453.                 else
  1454.                     fileBuffer[(ii + BUFFER_SIZES) + (i - BUFFER_SIZES)] = passBuffer[i - BUFFER_SIZES];
  1455.             }
  1456.         }
  1457.     }
  1458.  
  1459.     /*Clear out sensitive buffers ASAP*/
  1460.     /*Maybe I can multi-thread this*/
  1461.     OPENSSL_cleanse(entryBuffer, sizeof(unsigned char) * BUFFER_SIZES);
  1462.     OPENSSL_cleanse(passBuffer, sizeof(unsigned char) * BUFFER_SIZES);
  1463.     OPENSSL_cleanse(decryptedBuffer, sizeof(unsigned char) * fileSize + EVP_MAX_BLOCK_LENGTH);
  1464.  
  1465.     /*Clear the old encrypted information out to use encryptedBuffer to store cipher-text of modifications*/
  1466.     free(encryptedBuffer);
  1467.     encryptedBuffer = calloc(sizeof(unsigned char), outlen);
  1468.  
  1469.     fileSize = outlen;
  1470.  
  1471.     EVP_EncryptInit_ex(ctx, evpCipher1, NULL, evpKey1, evpIv1);
  1472.     if (!EVP_EncryptUpdate(ctx, encryptedBuffer, &outlen, fileBuffer, fileSize)) {
  1473.         /* Error */
  1474.         EVP_CIPHER_CTX_cleanup(ctx);
  1475.         OPENSSL_cleanse(fileBuffer, sizeof(unsigned char) * fileSize);
  1476.         free(entryBuffer);
  1477.         free(passBuffer);
  1478.         free(encryptedBuffer);
  1479.         free(decryptedBuffer);
  1480.         free(fileBuffer);
  1481.         free(ctx);
  1482.  
  1483.         cleanUpFiles();
  1484.         cleanUpBuffers();
  1485.         return 1;
  1486.     }
  1487.     /* Buffer passed to EVP_EncryptFinal() must be after data just
  1488.             * encrypted to avoid overwriting it.
  1489.             */
  1490.     if (!EVP_EncryptFinal_ex(ctx, encryptedBuffer + outlen, &tmplen)) {
  1491.         /* Error */
  1492.         EVP_CIPHER_CTX_cleanup(ctx);
  1493.         OPENSSL_cleanse(fileBuffer, sizeof(unsigned char) * fileSize);
  1494.         free(entryBuffer);
  1495.         free(passBuffer);
  1496.         free(encryptedBuffer);
  1497.         free(decryptedBuffer);
  1498.         free(fileBuffer);
  1499.         free(ctx);
  1500.  
  1501.         cleanUpFiles();
  1502.         cleanUpBuffers();
  1503.         return 1;
  1504.     }
  1505.     outlen += tmplen;
  1506.     EVP_CIPHER_CTX_cleanup(ctx);
  1507.  
  1508.     /*Clear out fileBuffer ASAP*/
  1509.     OPENSSL_cleanse(fileBuffer, sizeof(unsigned char) * fileSize);
  1510.  
  1511.     /*Append this as the "generated" MAC later*/
  1512.     HMAC(EVP_sha512(), hmacKey, SHA512_DIGEST_LENGTH, encryptedBuffer, outlen, gMac, gMacLength);
  1513.  
  1514.     /*Check if any entries were updated*/
  1515.     if (noEntryMatched == 1) {
  1516.         printf("Nothing matched the entry specified, nothing was deleted.\n");
  1517.     } else
  1518.         printf("If you updated more than you intended to, restore from %s.autobak\n", dbFileName);
  1519.  
  1520.     /*Write the modified cipher-text to this temporary file for sealEnvelope()*/
  1521.     tmpFile = fopen(tmpFile3, "wb");
  1522.     if (tmpFile == NULL) {
  1523.         perror("passmanager");
  1524.         return errno;
  1525.     }
  1526.     chmod(tmpFile3, S_IRUSR | S_IWUSR);
  1527.  
  1528.     /*Write the encryptedBuffer out and check for errors*/
  1529.     returnVal = fwrite(encryptedBuffer, fileSize, sizeof(unsigned char), tmpFile);
  1530.     if (returnVal != fileSize / sizeof(unsigned char))
  1531.         ;
  1532.     {
  1533.         if (ferror(tmpFile)) {
  1534.             printf("fwrite failed @ 1365\n");
  1535.             return 1;
  1536.         }
  1537.     }
  1538.  
  1539.     fclose(tmpFile);
  1540.  
  1541.     /*Free pointers used for buffers*/
  1542.     free(entryBuffer);
  1543.     free(passBuffer);
  1544.     free(encryptedBuffer);
  1545.     free(decryptedBuffer);
  1546.     free(fileBuffer);
  1547.     free(ctx);
  1548.  
  1549.     return 0;
  1550. }
  1551.  
  1552. int deletePass(FILE* dbFile, unsigned char* searchString)
  1553. {
  1554.     unsigned i, ii = 0, iii = 0;
  1555.     int lastCheck = 0;
  1556.     //int noEntryMatched = 1;
  1557.     int entriesMatched = 0;
  1558.  
  1559.     int outlen, tmplen;
  1560.  
  1561.     unsigned char* fileBuffer;
  1562.     unsigned char* fileBufferOld;
  1563.  
  1564.     FILE* tmpFile;
  1565.  
  1566.     unsigned char* entryBuffer = calloc(sizeof(unsigned char), BUFFER_SIZES);
  1567.     unsigned char* passBuffer = calloc(sizeof(unsigned char), BUFFER_SIZES);
  1568.  
  1569.     /*Get the filesize*/
  1570.     long fileSize;
  1571.     fseek(dbFile, 0L, SEEK_END);
  1572.     fileSize = ftell(dbFile);
  1573.     fseek(dbFile, 0L, SEEK_SET);
  1574.  
  1575.     unsigned char* encryptedBuffer = calloc(sizeof(unsigned char), fileSize + EVP_MAX_BLOCK_LENGTH);
  1576.     unsigned char* decryptedBuffer = calloc(sizeof(unsigned char), fileSize + EVP_MAX_BLOCK_LENGTH);
  1577.  
  1578.     returnVal = fread(encryptedBuffer, sizeof(unsigned char), fileSize, dbFile);
  1579.     if (returnVal != fileSize / sizeof(unsigned char)) {
  1580.         if (ferror(dbFile)) {
  1581.             printf("Fread failed in deletePass()\n");
  1582.             return 1;
  1583.         }
  1584.     }
  1585.  
  1586.     /*This will be the gMac as in generated MAC*/
  1587.     HMAC(EVP_sha512(), hmacKey, SHA512_DIGEST_LENGTH, encryptedBuffer, fileSize, gMac, gMacLength);
  1588.  
  1589.     /*Check if the MAC from the EVP2DecryptedFile matches MAC generated via HMAC*/
  1590.  
  1591.     /*Return error status before proceeding and clean up sensitive data*/
  1592.     if (memcmp(fMac, gMac, SHA512_DIGEST_LENGTH) != 0) {
  1593.         printMACErrMessage(backupFileName);
  1594.  
  1595.         free(entryBuffer);
  1596.         free(passBuffer);
  1597.         free(encryptedBuffer);
  1598.         free(decryptedBuffer);
  1599.         cleanUpFiles();
  1600.         cleanUpBuffers();
  1601.         return 1;
  1602.     }
  1603.  
  1604.     EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
  1605.     EVP_CIPHER_CTX_init(ctx);
  1606.  
  1607.     /*Now make a buffer for the file.  Reallocate later if we find a match to delete*/
  1608.     fileBuffer = calloc(sizeof(unsigned char), fileSize + EVP_MAX_BLOCK_LENGTH);
  1609.  
  1610.     EVP_DecryptInit(ctx, evpCipher1, evpKey1, evpIv1);
  1611.  
  1612.     /*Decrypt file and store into temp buffer*/
  1613.     if (!EVP_DecryptUpdate(ctx, decryptedBuffer, &outlen, encryptedBuffer, fileSize)) {
  1614.         /* Error */
  1615.         EVP_CIPHER_CTX_cleanup(ctx);
  1616.         OPENSSL_cleanse(decryptedBuffer, sizeof(unsigned char) * fileSize);
  1617.         free(entryBuffer);
  1618.         free(passBuffer);
  1619.         free(encryptedBuffer);
  1620.         free(decryptedBuffer);
  1621.         free(fileBuffer);
  1622.         free(ctx);
  1623.  
  1624.         cleanUpFiles();
  1625.         cleanUpBuffers();
  1626.         return 1;
  1627.     }
  1628.     /* Buffer passed to EVP_EncryptFinal() must be after data just
  1629.             * encrypted to avoid overwriting it.
  1630.             */
  1631.  
  1632.     if (!EVP_DecryptFinal_ex(ctx, decryptedBuffer + outlen, &tmplen)) {
  1633.         /* Error */
  1634.         EVP_CIPHER_CTX_cleanup(ctx);
  1635.         OPENSSL_cleanse(decryptedBuffer, sizeof(unsigned char) * fileSize);
  1636.         free(entryBuffer);
  1637.         free(passBuffer);
  1638.         free(encryptedBuffer);
  1639.         free(decryptedBuffer);
  1640.         free(fileBuffer);
  1641.         free(ctx);
  1642.  
  1643.         cleanUpFiles();
  1644.         cleanUpBuffers();
  1645.         return 1;
  1646.     }
  1647.     outlen += tmplen;
  1648.     EVP_CIPHER_CTX_cleanup(ctx);
  1649.  
  1650.     for (ii = 0; ii < outlen; ii += (BUFFER_SIZES * 2)) {
  1651.  
  1652.         /*Copy the encrypted information into the evp1Buffer*/
  1653.         for (i = 0; i < BUFFER_SIZES; i++) {
  1654.             entryBuffer[i] = decryptedBuffer[i + ii];
  1655.             passBuffer[i] = decryptedBuffer[i + ii + BUFFER_SIZES];
  1656.         }
  1657.  
  1658.         /*Use strcmp to match the exact entry here*/
  1659.         if ((lastCheck = strncmp(searchString, entryBuffer, strlen(searchString))) == 0) /*Now we're going to find the specific entry to delete it*/
  1660.         {
  1661.             if (ii == (fileSize - (BUFFER_SIZES * 2))) /*If ii is one entry short of fileSize*/
  1662.             {
  1663.                 if (entriesMatched < 1) /*If entry was matched we need to shrink the file buffer*/
  1664.                 {
  1665.                     /*Re-size the buffer to reflect deleted passwords*/
  1666.                     /*Not using realloc() because it will leak and prevent wiping sensitive information*/
  1667.                     fileBufferOld = calloc(sizeof(unsigned char), outlen - ((BUFFER_SIZES * 2) * entriesMatched));
  1668.                     memcpy(fileBufferOld, fileBuffer, sizeof(unsigned char) * outlen - ((BUFFER_SIZES * 2) * entriesMatched));
  1669.                     OPENSSL_cleanse(fileBuffer, sizeof(unsigned char) * outlen - ((BUFFER_SIZES * 2) * entriesMatched));
  1670.                     free(fileBuffer);
  1671.  
  1672.                     fileBuffer = calloc(sizeof(unsigned char), outlen - ((BUFFER_SIZES * 2) * entriesMatched));
  1673.                     memcpy(fileBuffer, fileBufferOld, sizeof(unsigned char) * outlen - ((BUFFER_SIZES * 2) * entriesMatched));
  1674.                     OPENSSL_cleanse(fileBufferOld, sizeof(unsigned char) * outlen - ((BUFFER_SIZES * 2) * entriesMatched));
  1675.                     free(fileBufferOld);
  1676.                 }
  1677.             }
  1678.             printf("Matched \"%s\" to \"%s\" (Deleting)...\n", searchString, entryBuffer);
  1679.             entriesMatched++;
  1680.         } else {
  1681.             for (i = 0; i < BUFFER_SIZES * 2; i++) {
  1682.                 if (i < BUFFER_SIZES)
  1683.                     fileBuffer[iii + i] = entryBuffer[i];
  1684.                 else
  1685.                     fileBuffer[(iii + BUFFER_SIZES) + (i - BUFFER_SIZES)] = passBuffer[i - BUFFER_SIZES];
  1686.             }
  1687.             iii += BUFFER_SIZES * 2;
  1688.         }
  1689.     }
  1690.  
  1691.     /*Clear out sensitive information ASAP*/
  1692.     OPENSSL_cleanse(entryBuffer, sizeof(unsigned char) * BUFFER_SIZES);
  1693.     OPENSSL_cleanse(passBuffer, sizeof(unsigned char) * BUFFER_SIZES);
  1694.     OPENSSL_cleanse(decryptedBuffer, sizeof(unsigned char) * fileSize);
  1695.  
  1696.     free(encryptedBuffer);
  1697.     encryptedBuffer = calloc(sizeof(unsigned char), outlen - ((BUFFER_SIZES * 2) * entriesMatched));
  1698.  
  1699.     fileSize = outlen;
  1700.  
  1701.     EVP_EncryptInit_ex(ctx, evpCipher1, NULL, evpKey1, evpIv1);
  1702.     if (!EVP_EncryptUpdate(ctx, encryptedBuffer, &outlen, fileBuffer, fileSize - ((BUFFER_SIZES * 2) * entriesMatched))) {
  1703.         /* Error */
  1704.         EVP_CIPHER_CTX_cleanup(ctx);
  1705.         OPENSSL_cleanse(fileBuffer, sizeof(unsigned char) * (fileSize - ((BUFFER_SIZES * 2) * entriesMatched)));
  1706.         free(entryBuffer);
  1707.         free(passBuffer);
  1708.         free(encryptedBuffer);
  1709.         free(decryptedBuffer);
  1710.         free(fileBuffer);
  1711.         free(ctx);
  1712.  
  1713.         cleanUpFiles();
  1714.         cleanUpBuffers();
  1715.         return 1;
  1716.     }
  1717.     /* Buffer passed to EVP_EncryptFinal() must be after data just
  1718.             * encrypted to avoid overwriting it.
  1719.             */
  1720.     if (!EVP_EncryptFinal_ex(ctx, encryptedBuffer + outlen, &tmplen)) {
  1721.         /* Error */
  1722.         EVP_CIPHER_CTX_cleanup(ctx);
  1723.         OPENSSL_cleanse(fileBuffer, sizeof(unsigned char) * (fileSize - ((BUFFER_SIZES * 2) * entriesMatched)));
  1724.         free(entryBuffer);
  1725.         free(passBuffer);
  1726.         free(encryptedBuffer);
  1727.         free(decryptedBuffer);
  1728.         free(fileBuffer);
  1729.         free(ctx);
  1730.  
  1731.         cleanUpFiles();
  1732.         cleanUpBuffers();
  1733.         return 1;
  1734.     }
  1735.     outlen += tmplen;
  1736.     EVP_CIPHER_CTX_cleanup(ctx);
  1737.  
  1738.     /*Clear out sensitive information in fileBuffer ASAP*/
  1739.     OPENSSL_cleanse(fileBuffer, sizeof(unsigned char) * fileSize - ((BUFFER_SIZES * 2) * entriesMatched));
  1740.  
  1741.     /*Append this as the "generated" MAC later*/
  1742.     HMAC(EVP_sha512(), hmacKey, SHA512_DIGEST_LENGTH, encryptedBuffer, fileSize - ((BUFFER_SIZES * 2) * entriesMatched), gMac, gMacLength);
  1743.  
  1744.     /*Write the modified cipher-text to this temporary file for sealEnvelope()*/
  1745.     tmpFile = fopen(tmpFile3, "wb");
  1746.     if (tmpFile == NULL) {
  1747.         perror("passmanager");
  1748.         return errno;
  1749.     }
  1750.     chmod(tmpFile3, S_IRUSR | S_IWUSR);
  1751.  
  1752.     if (entriesMatched < 1) {
  1753.         printf("Nothing matched that exactly.\n");
  1754.         returnVal = fwrite(encryptedBuffer, fileSize, sizeof(unsigned char), tmpFile);
  1755.         if (returnVal != fileSize / sizeof(unsigned char))
  1756.             ;
  1757.         {
  1758.             if (ferror(tmpFile)) {
  1759.                 printf("fwrite failed @ 1550\n");
  1760.                 return 1;
  1761.             }
  1762.         }
  1763.     } else {
  1764.         printf("If you deleted more than you intended to, restore from %s.autobak\n", dbFileName);
  1765.         returnVal = fwrite(encryptedBuffer, fileSize - ((BUFFER_SIZES * 2) * entriesMatched), sizeof(unsigned char), tmpFile);
  1766.         if (returnVal != fileSize - ((BUFFER_SIZES * 2) * entriesMatched) / sizeof(unsigned char))
  1767.             ;
  1768.         {
  1769.             if (ferror(tmpFile)) {
  1770.                 printf("fwrite failed @ 1558\n");
  1771.                 return 1;
  1772.             }
  1773.         }
  1774.     }
  1775.     fclose(tmpFile);
  1776.  
  1777.     free(entryBuffer);
  1778.     free(passBuffer);
  1779.     free(encryptedBuffer);
  1780.     free(decryptedBuffer);
  1781.     free(fileBuffer);
  1782.     free(ctx);
  1783.  
  1784.     return 0;
  1785. }
  1786.  
  1787. int updateEncPass(FILE* dbFile)
  1788. {
  1789.     //int i;
  1790.     int outlen, tmplen;
  1791.  
  1792.     FILE* tmpFile;
  1793.  
  1794.     /*Get the filesize*/
  1795.     long fileSize;
  1796.     fseek(dbFile, 0L, SEEK_END);
  1797.     fileSize = ftell(dbFile);
  1798.     fseek(dbFile, 0L, SEEK_SET);
  1799.  
  1800.     unsigned char* decryptedBuffer = calloc(sizeof(unsigned char), fileSize + EVP_MAX_BLOCK_LENGTH);
  1801.     unsigned char* encryptedBuffer = calloc(sizeof(unsigned char), fileSize + EVP_MAX_BLOCK_LENGTH);
  1802.  
  1803.     returnVal = fread(encryptedBuffer, sizeof(unsigned char), fileSize, dbFile);
  1804.     if (returnVal != fileSize / sizeof(unsigned char)) {
  1805.         if (ferror(dbFile)) {
  1806.             printf("Fread failed in updateEncPass()\n");
  1807.             return 1;
  1808.         }
  1809.     }
  1810.  
  1811.     /*This will be the gMac as in generated MAC*/
  1812.     HMAC(EVP_sha512(), hmacKeyOld, SHA512_DIGEST_LENGTH, encryptedBuffer, fileSize, gMac, gMacLength);
  1813.  
  1814.     /*Check if the MAC from the EVP2DecryptedFile matches MAC generated via HMAC)*/
  1815.  
  1816.     /*Return error status before proceeding and clean up sensitive data*/
  1817.     if (memcmp(fMac, gMac, SHA512_DIGEST_LENGTH) != 0) {
  1818.         printMACErrMessage(backupFileName);
  1819.  
  1820.         free(decryptedBuffer);
  1821.         free(encryptedBuffer);
  1822.         cleanUpFiles();
  1823.         cleanUpBuffers();
  1824.         return 1;
  1825.     }
  1826.  
  1827.     memcpy(hmacKey, hmacKeyOld, sizeof(unsigned char) * SHA512_DIGEST_LENGTH);
  1828.  
  1829.     /*evpKDF() needs to run before ctx is initialized with EVP_CIPHER_CTX_new*/
  1830.  
  1831.     EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
  1832.     EVP_CIPHER_CTX_init(ctx);
  1833.     EVP_DecryptInit(ctx, evpCipher1Old, evpKey1Old, evpIv1Old);
  1834.  
  1835.     /*Decrypted the data into decryptedBuffer*/
  1836.  
  1837.     if (!EVP_DecryptUpdate(ctx, decryptedBuffer, &outlen, encryptedBuffer, fileSize)) {
  1838.         /* Error */
  1839.         EVP_CIPHER_CTX_cleanup(ctx);
  1840.         OPENSSL_cleanse(decryptedBuffer, sizeof(unsigned char) * fileSize + EVP_MAX_BLOCK_LENGTH);
  1841.         free(decryptedBuffer);
  1842.         free(encryptedBuffer);
  1843.         free(ctx);
  1844.         return 1;
  1845.     }
  1846.     /* Buffer passed to EVP_EncryptFinal() must be after data just
  1847.             * encrypted to avoid overwriting it.
  1848.             */
  1849.  
  1850.     if (!EVP_DecryptFinal_ex(ctx, decryptedBuffer + outlen, &tmplen)) {
  1851.         /* Error */
  1852.         EVP_CIPHER_CTX_cleanup(ctx);
  1853.         OPENSSL_cleanse(decryptedBuffer, sizeof(unsigned char) * fileSize + EVP_MAX_BLOCK_LENGTH);
  1854.         free(decryptedBuffer);
  1855.         free(encryptedBuffer);
  1856.         free(ctx);
  1857.         return 1;
  1858.     }
  1859.     outlen += tmplen;
  1860.     EVP_CIPHER_CTX_cleanup(ctx);
  1861.        
  1862.     if(evpKDF(dbPass, evp1Salt, EVP1_SALT_SIZE,evpCipher1,evpDigest1,evpKey1,evpIv1) != 0) {
  1863.             return 1;
  1864.     }
  1865.  
  1866.     memcpy(hmacKey, hmacKeyNew, sizeof(unsigned char) * SHA512_DIGEST_LENGTH);
  1867.  
  1868.     fileSize = outlen;
  1869.  
  1870.     EVP_EncryptInit_ex(ctx, evpCipher1, NULL, evpKey1, evpIv1);
  1871.     if (!EVP_EncryptUpdate(ctx, encryptedBuffer, &outlen, decryptedBuffer, fileSize)) {
  1872.         /* Error */
  1873.         EVP_CIPHER_CTX_cleanup(ctx);
  1874.         OPENSSL_cleanse(decryptedBuffer, sizeof(unsigned char) * fileSize + EVP_MAX_BLOCK_LENGTH);
  1875.         free(decryptedBuffer);
  1876.         free(encryptedBuffer);
  1877.         free(ctx);
  1878.         return 1;
  1879.     }
  1880.     /* Buffer passed to EVP_EncryptFinal() must be after data just
  1881.             * encrypted to avoid overwriting it.
  1882.             */
  1883.     if (!EVP_EncryptFinal_ex(ctx, encryptedBuffer + outlen, &tmplen)) {
  1884.         /* Error */
  1885.         EVP_CIPHER_CTX_cleanup(ctx);
  1886.         OPENSSL_cleanse(decryptedBuffer, sizeof(unsigned char) * fileSize + EVP_MAX_BLOCK_LENGTH);
  1887.         free(decryptedBuffer);
  1888.         free(encryptedBuffer);
  1889.         free(ctx);
  1890.         return 1;
  1891.     }
  1892.     outlen += tmplen;
  1893.     EVP_CIPHER_CTX_cleanup(ctx);
  1894.  
  1895.     /*Clear sensitive data from decryptedBuffer ASAP*/
  1896.     OPENSSL_cleanse(decryptedBuffer, sizeof(unsigned char) * fileSize);
  1897.  
  1898.     /*Append this as the "generated" MAC later*/
  1899.     HMAC(EVP_sha512(), hmacKey, SHA512_DIGEST_LENGTH, encryptedBuffer, fileSize, gMac, gMacLength);
  1900.  
  1901.     tmpFile = fopen(tmpFile3, "wb"); /*Now open a temp file just to write the new evp1 data to, clean up in the calling function*/
  1902.     if (tmpFile == NULL) /*Make sure the file opens*/
  1903.     {
  1904.         perror("passmanager");
  1905.         return errno;
  1906.     }
  1907.     chmod(tmpFile3, S_IRUSR | S_IWUSR);
  1908.  
  1909.     returnVal = fwrite(encryptedBuffer, fileSize, sizeof(unsigned char), tmpFile);
  1910.     if (returnVal != fileSize / sizeof(unsigned char))
  1911.         ;
  1912.     {
  1913.         if (ferror(tmpFile)) {
  1914.             printf("fwrite failed @ 1707\n");
  1915.             return 1;
  1916.         }
  1917.     }
  1918.     fclose(tmpFile);
  1919.  
  1920.     free(decryptedBuffer);
  1921.     free(encryptedBuffer);
  1922.     free(ctx);
  1923.  
  1924.     return 0;
  1925. }
  1926.  
  1927. int writePass(FILE* dbFile)
  1928. {
  1929.     /*We need a set of incrementors to crawl through buffers*/
  1930.     unsigned i;
  1931.     long fileSize;
  1932.  
  1933.     unsigned char outbuf[1024 + EVP_MAX_BLOCK_LENGTH];
  1934.     int outlen, tmplen;
  1935.     EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
  1936.     EVP_CIPHER_CTX_init(ctx);
  1937.  
  1938.     /*Get the filesize*/
  1939.     fseek(dbFile, 0L, SEEK_END);
  1940.     fileSize = ftell(dbFile);
  1941.     fseek(dbFile, 0L, SEEK_SET);
  1942.  
  1943.     /*entryPass and entryName are both copied into infoBuffer, which is then encrypted*/
  1944.     unsigned char* infoBuffer = calloc(sizeof(unsigned char), BUFFER_SIZES * 2);
  1945.     unsigned char* decryptedBuffer = calloc(sizeof(unsigned char), fileSize + (BUFFER_SIZES * 2) + EVP_MAX_BLOCK_LENGTH);
  1946.     unsigned char* encryptedBuffer = calloc(sizeof(unsigned char), fileSize + EVP_MAX_BLOCK_LENGTH);
  1947.  
  1948.     /*Put the unsigned chars, include random whitespace ones, from entryName and entryPass into infoBuffer, again splitting the BUFFER_SIZES * 2 unsigned chars between the two*/
  1949.     for (i = 0; i < BUFFER_SIZES; i++)
  1950.         infoBuffer[i] = entryName[i];
  1951.     for (i = 0; i < BUFFER_SIZES; i++)
  1952.         infoBuffer[i + BUFFER_SIZES] = entryPass[i];
  1953.  
  1954.     /*Store encrypted file in buffer*/
  1955.     returnVal = fread(encryptedBuffer, sizeof(unsigned char), fileSize, dbFile);
  1956.     if (returnVal != fileSize / sizeof(unsigned char)) {
  1957.         if (ferror(dbFile)) {
  1958.             printf("Fread failed in writePass()\n");
  1959.             return 1;
  1960.         }
  1961.     }
  1962.  
  1963.     if (toggle.firstRun != 1) {
  1964.  
  1965.         /*This will be the gMac as in generated MAC*/
  1966.         HMAC(EVP_sha512(), hmacKey, SHA512_DIGEST_LENGTH, encryptedBuffer, fileSize, gMac, gMacLength);
  1967.  
  1968.         /*Check if the MAC from the EVP2DecryptedFile matches MAC generated via HMAC*/
  1969.  
  1970.         /*Return error status before proceeding and clean up sensitive data*/
  1971.         if (memcmp(fMac, gMac, SHA512_DIGEST_LENGTH) != 0) {
  1972.             printMACErrMessage(backupFileName);
  1973.             OPENSSL_cleanse(infoBuffer, sizeof(unsigned char) * BUFFER_SIZES * 2);
  1974.  
  1975.             free(infoBuffer);
  1976.             free(decryptedBuffer);
  1977.             free(encryptedBuffer);
  1978.             cleanUpFiles();
  1979.             cleanUpBuffers();
  1980.             return 1;
  1981.         }
  1982.  
  1983.         EVP_DecryptInit(ctx, evpCipher1, evpKey1, evpIv1);
  1984.  
  1985.         /*Decrypt file and store into temp buffer*/
  1986.         if (!EVP_DecryptUpdate(ctx, decryptedBuffer, &outlen, encryptedBuffer, fileSize)) {
  1987.             /* Error */
  1988.             EVP_CIPHER_CTX_cleanup(ctx);
  1989.             OPENSSL_cleanse(decryptedBuffer, sizeof(unsigned char) * (fileSize + (BUFFER_SIZES * 2) + EVP_MAX_BLOCK_LENGTH));
  1990.             OPENSSL_cleanse(infoBuffer, sizeof(unsigned char) * BUFFER_SIZES * 2);
  1991.             free(infoBuffer);
  1992.             free(decryptedBuffer);
  1993.             free(encryptedBuffer);
  1994.             free(ctx);
  1995.  
  1996.             cleanUpFiles();
  1997.             cleanUpBuffers();
  1998.             return 1;
  1999.         }
  2000.         /* Buffer passed to EVP_EncryptFinal() must be after data just
  2001.             * encrypted to avoid overwriting it.
  2002.             */
  2003.  
  2004.         if (!EVP_DecryptFinal_ex(ctx, decryptedBuffer + outlen, &tmplen)) {
  2005.             /* Error */
  2006.             EVP_CIPHER_CTX_cleanup(ctx);
  2007.             OPENSSL_cleanse(decryptedBuffer, sizeof(unsigned char) * (fileSize + (BUFFER_SIZES * 2) + EVP_MAX_BLOCK_LENGTH));
  2008.             OPENSSL_cleanse(infoBuffer, sizeof(unsigned char) * BUFFER_SIZES * 2);
  2009.             free(infoBuffer);
  2010.             free(decryptedBuffer);
  2011.             free(encryptedBuffer);
  2012.             free(ctx);
  2013.  
  2014.             cleanUpFiles();
  2015.             cleanUpBuffers();
  2016.             return 1;
  2017.         }
  2018.         outlen += tmplen;
  2019.         EVP_CIPHER_CTX_cleanup(ctx);
  2020.     }
  2021.  
  2022.     if (toggle.firstRun == 1) {
  2023.         EVP_EncryptInit_ex(ctx, evpCipher1, NULL, evpKey1, evpIv1);
  2024.  
  2025.         /*This looping operation is different than the one in printPasses, because it encrypts and writes the whole buffer to file*/
  2026.  
  2027.         if (!EVP_EncryptUpdate(ctx, outbuf, &outlen, infoBuffer, BUFFER_SIZES * 2)) {
  2028.             /* Error */
  2029.             EVP_CIPHER_CTX_cleanup(ctx);
  2030.             OPENSSL_cleanse(infoBuffer, sizeof(unsigned char) * BUFFER_SIZES * 2);
  2031.             free(infoBuffer);
  2032.             free(decryptedBuffer);
  2033.             free(encryptedBuffer);
  2034.             free(ctx);
  2035.  
  2036.             cleanUpFiles();
  2037.             cleanUpBuffers();
  2038.             return 1;
  2039.         }
  2040.         /* Buffer passed to EVP_EncryptFinal() must be after data just
  2041.             * encrypted to avoid overwriting it.
  2042.             */
  2043.  
  2044.         if (!EVP_EncryptFinal_ex(ctx, outbuf + outlen, &tmplen)) {
  2045.             /* Error */
  2046.             EVP_CIPHER_CTX_cleanup(ctx);
  2047.             OPENSSL_cleanse(infoBuffer, sizeof(unsigned char) * BUFFER_SIZES * 2);
  2048.             free(infoBuffer);
  2049.             free(decryptedBuffer);
  2050.             free(encryptedBuffer);
  2051.             free(ctx);
  2052.  
  2053.             cleanUpFiles();
  2054.             cleanUpBuffers();
  2055.             return 1;
  2056.         }
  2057.         outlen += tmplen;
  2058.         EVP_CIPHER_CTX_cleanup(ctx);
  2059.  
  2060.         /*Clear out sensitive information in infoBuffer ASAP*/
  2061.         OPENSSL_cleanse(infoBuffer, sizeof(unsigned char) * BUFFER_SIZES * 2);
  2062.  
  2063.         /*Hash the evp1 data with HMAC-SHA512*/
  2064.         /*Append this as the "generated" MAC later*/
  2065.         HMAC(EVP_sha512(), hmacKey, SHA512_DIGEST_LENGTH, outbuf, outlen, gMac, gMacLength);
  2066.  
  2067.         /*Write the encrypted information to file*/
  2068.         returnVal = fwrite(outbuf, 1, sizeof(unsigned char) * outlen, dbFile);
  2069.         if (returnVal != outlen * sizeof(unsigned char))
  2070.             ;
  2071.         {
  2072.             if (ferror(dbFile)) {
  2073.                 printf("fwrite failed @ 1837\n");
  2074.                 return 1;
  2075.             }
  2076.         }
  2077.  
  2078.     } else {
  2079.  
  2080.         EVP_EncryptInit_ex(ctx, evpCipher1, NULL, evpKey1, evpIv1);
  2081.  
  2082.         OPENSSL_cleanse(encryptedBuffer, sizeof(unsigned char) * fileSize);
  2083.         free(encryptedBuffer);
  2084.         encryptedBuffer = calloc(sizeof(unsigned char), outlen + (BUFFER_SIZES * 2) + EVP_MAX_BLOCK_LENGTH);
  2085.  
  2086.         for (i = 0; i < BUFFER_SIZES * 2; i++) {
  2087.             decryptedBuffer[outlen + i] = infoBuffer[i];
  2088.         }
  2089.  
  2090.         OPENSSL_cleanse(infoBuffer, sizeof(unsigned char) * BUFFER_SIZES * 2);
  2091.  
  2092.         fileSize = outlen;
  2093.  
  2094.         if (!EVP_EncryptUpdate(ctx, encryptedBuffer, &outlen, decryptedBuffer, fileSize + (BUFFER_SIZES * 2))) {
  2095.             /* Error */
  2096.             EVP_CIPHER_CTX_cleanup(ctx);
  2097.             OPENSSL_cleanse(decryptedBuffer, sizeof(unsigned char) * (fileSize + (BUFFER_SIZES * 2) + EVP_MAX_BLOCK_LENGTH));
  2098.             free(infoBuffer);
  2099.             free(decryptedBuffer);
  2100.             free(encryptedBuffer);
  2101.             free(ctx);
  2102.  
  2103.             cleanUpFiles();
  2104.             cleanUpBuffers();
  2105.             return 1;
  2106.         }
  2107.         /* Buffer passed to EVP_EncryptFinal() must be after data just
  2108.             * encrypted to avoid overwriting it.
  2109.             */
  2110.         if (!EVP_EncryptFinal_ex(ctx, encryptedBuffer + outlen, &tmplen)) {
  2111.             /* Error */
  2112.             EVP_CIPHER_CTX_cleanup(ctx);
  2113.             OPENSSL_cleanse(decryptedBuffer, sizeof(unsigned char) * (fileSize + (BUFFER_SIZES * 2) + EVP_MAX_BLOCK_LENGTH));
  2114.             free(infoBuffer);
  2115.             free(decryptedBuffer);
  2116.             free(encryptedBuffer);
  2117.             free(ctx);
  2118.  
  2119.             cleanUpFiles();
  2120.             cleanUpBuffers();
  2121.             return 1;
  2122.         }
  2123.         outlen += tmplen;
  2124.         EVP_CIPHER_CTX_cleanup(ctx);
  2125.  
  2126.         OPENSSL_cleanse(decryptedBuffer, sizeof(unsigned char) * fileSize + (BUFFER_SIZES * 2) + EVP_MAX_BLOCK_LENGTH);
  2127.  
  2128.         HMAC(EVP_sha512(), hmacKey, SHA512_DIGEST_LENGTH, encryptedBuffer, outlen, gMac, gMacLength);
  2129.  
  2130.         fclose(dbFile);
  2131.         wipeFile(tmpFile2);
  2132.         dbFile = fopen(tmpFile2, "wb");
  2133.  
  2134.         returnVal = fwrite(encryptedBuffer, 1, outlen * sizeof(unsigned char), dbFile);
  2135.         if (returnVal != outlen * sizeof(unsigned char))
  2136.             ;
  2137.         {
  2138.             if (ferror(dbFile)) {
  2139.                 printf("fwrite failed @ 1881\n");
  2140.                 return 1;
  2141.             }
  2142.         }
  2143.     }
  2144.  
  2145.     free(infoBuffer);
  2146.     free(decryptedBuffer);
  2147.     free(encryptedBuffer);
  2148.     free(ctx);
  2149.  
  2150.     fclose(dbFile);
  2151.     return 0;
  2152. }
  2153.  
  2154. /*Over write the data we put in the temporary files with Schneier 7-Pass Method*/
  2155. /*https://en.wikipedia.org/wiki/Data_remanence#Feasibility_of_recovering_overwritten_data*/
  2156. /*https://en.wikipedia.org/wiki/Data_erasure#Standards*/
  2157. int wipeFile(const unsigned char* filename)
  2158. {
  2159.     int fileSize = returnFileSize(filename);
  2160.     unsigned i, ii, passes = 7;
  2161.     unsigned char b;
  2162.     FILE* fileToWrite;
  2163.     for (ii = 0; ii <= passes; ii++) {
  2164.         fileToWrite = fopen(filename, "w+");
  2165.         if (fileToWrite == NULL) /*Make sure the file opens*/
  2166.         {
  2167.             perror("passmanager");
  2168.             return errno;
  2169.         }
  2170.         if (ii == 0) {
  2171.             for (i = 0; i <= fileSize; i++)
  2172.                 fprintf(fileToWrite, "%i", 1);
  2173.         } else if (ii == 1) {
  2174.             for (i = 0; i <= fileSize; i++)
  2175.                 fprintf(fileToWrite, "%i", 0);
  2176.  
  2177.         } else {
  2178.             for (i = 0; i <= fileSize; i++) {
  2179.                 if (!RAND_bytes(&b, 1)) {
  2180.                     printf("Failure: CSPRNG bytes could not be made unpredictable\n");
  2181.                 }
  2182.                 fprintf(fileToWrite, "%c", 0);
  2183.             }
  2184.         }
  2185.         fclose(fileToWrite);
  2186.     }
  2187.     return 0;
  2188. }
  2189.  
  2190. /*Use stat() to check if a file exists. Returns 0 on success*/
  2191. int doesFileExist(const unsigned char* filename)
  2192. {
  2193.     struct stat st;
  2194.     int result = stat(filename, &st);
  2195.     return result;
  2196. }
  2197.  
  2198. /*Use stat() to return the filesize of file given at filename*/
  2199. int returnFileSize(const unsigned char* filename)
  2200. {
  2201.     struct stat st;
  2202.     stat(filename, &st);
  2203.     return st.st_size;
  2204. }
  2205.  
  2206. /*OpenSSL EVP routines to encrypt in sealEnvelope()*/
  2207. /*Would be great to get these to work on memory buffers instead of files*/
  2208. /*Whenever I do however, EVP_EncryptFinal_ex only outputs 16 bytes of nonsense*/
  2209. /*Code was gleamed from OpenSSL man pages for EVP_EncryptInit*/
  2210. int dbEncrypt(FILE* in, FILE* out)
  2211. {
  2212.     /* Allow enough space in output buffer for additional block */
  2213.     unsigned char inbuf[EVP_BLOCK_SIZE], outbuf[EVP_BLOCK_SIZE + EVP_MAX_BLOCK_LENGTH];
  2214.     int inlen, outlen;
  2215.     EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
  2216.     EVP_CIPHER_CTX_init(ctx);
  2217.     EVP_EncryptInit_ex(ctx, evpCipher2, NULL, evpKey2, evpIv2);
  2218.  
  2219.     for (;;) {
  2220.         inlen = fread(inbuf, 1, EVP_BLOCK_SIZE, in);
  2221.         if (inlen <= 0)
  2222.             break;
  2223.         if (!EVP_EncryptUpdate(ctx, outbuf, &outlen, inbuf, inlen)) {
  2224.             /* Error */
  2225.             EVP_CIPHER_CTX_cleanup(ctx);
  2226.             return 1;
  2227.         }
  2228.         returnVal = fwrite(outbuf, 1, outlen, out);
  2229.         if (returnVal != outlen)
  2230.             ;
  2231.         {
  2232.             if (ferror(out)) {
  2233.                 printf("fwrite failed 1975\n");
  2234.                 return 1;
  2235.             }
  2236.         }
  2237.     }
  2238.     if (!EVP_EncryptFinal_ex(ctx, outbuf, &outlen)) {
  2239.         /* Error */
  2240.         EVP_CIPHER_CTX_cleanup(ctx);
  2241.         return 1;
  2242.     }
  2243.     returnVal = fwrite(outbuf, 1, outlen, out);
  2244.     if (returnVal != outlen)
  2245.         ;
  2246.     {
  2247.         if (ferror(out)) {
  2248.             printf("fwrite failed 1987\n");
  2249.             return 1;
  2250.         }
  2251.     }
  2252.     EVP_CIPHER_CTX_cleanup(ctx);
  2253.     free(ctx);
  2254.     return 0;
  2255. }
  2256.  
  2257. /*OpenSSL EVP routines to decrypt*/
  2258. /*Basically the same operation but to be used in openEnvelope()*/
  2259. int dbDecrypt(FILE* in, FILE* out)
  2260. {
  2261.     /* Allow enough space in output buffer for additional block */
  2262.     unsigned char inbuf[EVP_BLOCK_SIZE], outbuf[EVP_BLOCK_SIZE + EVP_MAX_BLOCK_LENGTH];
  2263.     int inlen, outlen;
  2264.     EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
  2265.     EVP_CIPHER_CTX_init(ctx);
  2266.     EVP_DecryptInit(ctx, evpCipher2, evpKey2, evpIv2);
  2267.  
  2268.     for (;;) {
  2269.         inlen = fread(inbuf, 1, EVP_BLOCK_SIZE, in);
  2270.         if (inlen <= 0)
  2271.             break;
  2272.         if (!EVP_DecryptUpdate(ctx, outbuf, &outlen, inbuf, inlen)) {
  2273.             /* Error */
  2274.             EVP_CIPHER_CTX_cleanup(ctx);
  2275.             return 1;
  2276.         }
  2277.         returnVal = fwrite(outbuf, 1, outlen, out);
  2278.         if (returnVal != outlen)
  2279.             ;
  2280.         {
  2281.             if (ferror(out)) {
  2282.                 printf("fwrite failed @ 2018\n");
  2283.                 return 1;
  2284.             }
  2285.         }
  2286.     }
  2287.     if (!EVP_DecryptFinal_ex(ctx, outbuf, &outlen)) {
  2288.         /* Error */
  2289.         EVP_CIPHER_CTX_cleanup(ctx);
  2290.         return 1;
  2291.     }
  2292.     returnVal = fwrite(outbuf, 1, outlen, out);
  2293.     if (returnVal != outlen)
  2294.         ;
  2295.     {
  2296.         if (ferror(out)) {
  2297.             printf("fwrite failed @ 2030\n");
  2298.             return 1;
  2299.         }
  2300.     }
  2301.     EVP_CIPHER_CTX_cleanup(ctx);
  2302.     free(ctx);
  2303.     return 0;
  2304. }
  2305.  
  2306. /*To be honest I'm not really sure how this works*/
  2307. /*Borrowed from StackOverflow*/
  2308. /*https://stackoverflow.com/questions/47476427/get-a-list-of-all-supported-digest-algorithms*/
  2309. void encList(const OBJ_NAME* obj, void* arg)
  2310. {
  2311.     printf("Cipher: %s\n", obj->name);
  2312. }
  2313.  
  2314. /*Print out a list of cipher algorithms available to OpenSSL to use*/
  2315. void encLister()
  2316. {
  2317.     void* my_arg;
  2318.     OpenSSL_add_all_ciphers(); //make sure they're loaded
  2319.  
  2320.     my_arg = NULL;
  2321.     OBJ_NAME_do_all(OBJ_NAME_TYPE_CIPHER_METH, encList, my_arg);
  2322. }
  2323.  
  2324. /*Same as encList but for message digest*/
  2325. void mdList(const OBJ_NAME* obj, void* arg)
  2326. {
  2327.     printf("Digest: %s\n", obj->name);
  2328. }
  2329.  
  2330. void mdLister()
  2331. {
  2332.     void* my_arg;
  2333.     OpenSSL_add_all_digests(); //make sure they're loaded
  2334.  
  2335.     my_arg = NULL;
  2336.     OBJ_NAME_do_all(OBJ_NAME_TYPE_MD_METH, mdList, my_arg);
  2337. }
  2338.  
  2339. /*This function will load the appropriate cipher/digest structures based on user choice*/
  2340. /*Will also enforce CFB, OFB or CTR modes*/
  2341. int primeSSL()
  2342. {
  2343.     unsigned char modeTag[3];
  2344.     int stringStart, modeLength;
  2345.     unsigned i;
  2346.  
  2347.     /*If the user has specified a cipher to use*/
  2348.     if (toggle.encCipher == 1 || encCipher2[0] != 0) {
  2349.  
  2350.         /*Find start of mode*/
  2351.         for (i = strlen(encCipher1); i > 0; i--) {
  2352.             if (encCipher1[i] == '-') {
  2353.                 stringStart = i;
  2354.                 break;
  2355.             }
  2356.         }
  2357.  
  2358.         /*If no hyphen present, append -ctr mode to encCipher to enforce CTR mode by default*/
  2359.         if (i == 0) {
  2360.             printf("Must specify key size in bits and mode like \'%s-bits-mode\'\n", encCipher1);
  2361.             return 1;
  2362.         } else { /*Otherwise copy the mode specified to modeTag*/
  2363.  
  2364.             modeLength = strlen(encCipher1) - stringStart;
  2365.  
  2366.             /*Increment stringStart so it points to the first character of the mode string after the hyphen*/
  2367.             stringStart++;
  2368.  
  2369.             for (i = 0; i < modeLength; i++)
  2370.                 modeTag[i] = encCipher1[stringStart + i];
  2371.         }
  2372.  
  2373.         if (strcasecmp(modeTag, "ofb") == 0 || strcasecmp(modeTag, "cfb") >= 0 || strcasecmp(modeTag, "ctr") == 0) {
  2374.             evpCipher1 = EVP_get_cipherbyname(encCipher1);
  2375.         } else {
  2376.             printf("\n%s mode specified\nCipher should be in OFB, CFB or CTR mode\n", modeTag);
  2377.             return 1;
  2378.         }
  2379.  
  2380.         for (i = strlen(encCipher2); i > 0; i--) {
  2381.             if (encCipher2[i] == '-') {
  2382.                 stringStart = i;
  2383.                 break;
  2384.             }
  2385.         }
  2386.  
  2387.         if (i == 0) {
  2388.             printf("Must specify key size in bits and mode like \'%s-bits-mode\'\n", encCipher2);
  2389.             return 1;
  2390.         } else {
  2391.  
  2392.             modeLength = strlen(encCipher2) - stringStart;
  2393.  
  2394.             /*Increment stringStart so it points to the first character of the mode string after the hyphen*/
  2395.             stringStart++;
  2396.  
  2397.             for (i = 0; i < modeLength; i++)
  2398.                 modeTag[i] = encCipher2[stringStart + i];
  2399.         }
  2400.  
  2401.         if (strcasecmp(modeTag, "ofb") == 0 || strcasecmp(modeTag, "cfb") >= 0 || strcasecmp(modeTag, "ctr") == 0) {
  2402.             evpCipher2 = EVP_get_cipherbyname(encCipher2);
  2403.         } else {
  2404.             printf("\n%s mode specified\nCipher should be in OFB, CFB or CTR mode\n", modeTag);
  2405.             return 1;
  2406.         }
  2407.  
  2408.         /*If the cipher doesn't exists or there was a problem loading it return with error status*/
  2409.         if (!evpCipher1) {
  2410.             fprintf(stderr, "no such cipher\n");
  2411.             return 1;
  2412.         }
  2413.         evpCipher2 = EVP_get_cipherbyname(encCipher2);
  2414.         /*If the cipher doesn't exists or there was a problem loading it return with error status*/
  2415.         if (!evpCipher2) {
  2416.             fprintf(stderr, "no such cipher\n");
  2417.             return 1;
  2418.         }
  2419.  
  2420.     } else { /*If not default to aes-256-ctr*/
  2421.         strcpy(encCipher2, "aes-256-ctr");
  2422.         evpCipher2 = EVP_get_cipherbyname(encCipher2);
  2423.         if (!evpCipher2) { /*If that's not a valid cipher name*/
  2424.             fprintf(stderr, "no such cipher\n");
  2425.             return 1;
  2426.         }
  2427.         strcpy(encCipher1, "camellia-256-ofb");
  2428.         evpCipher1 = EVP_get_cipherbyname(encCipher1);
  2429.         if (!evpCipher1) { /*If that's not a valid cipher name*/
  2430.             fprintf(stderr, "no such cipher\n");
  2431.             return 1;
  2432.         }
  2433.     }
  2434.  
  2435.     /*If the user has specified a digest to use*/
  2436.     if (toggle.messageDigest == 1 || messageDigest2[0] != 0) {
  2437.         evpDigest1 = EVP_get_digestbyname(messageDigest1);
  2438.         if (!evpDigest1) {
  2439.             fprintf(stderr, "no such digest\n");
  2440.             return 1;
  2441.         }
  2442.         evpDigest2 = EVP_get_digestbyname(messageDigest2);
  2443.         if (!evpDigest2) {
  2444.             fprintf(stderr, "no such digest\n");
  2445.             return 1;
  2446.         }
  2447.     } else { /*If not default to sha512*/
  2448.         strcpy(messageDigest2, "sha512");
  2449.         evpDigest2 = EVP_get_digestbyname(messageDigest2);
  2450.         if (!evpDigest2) { /*If that's not a valid digest name*/
  2451.             fprintf(stderr, "no such digest\n");
  2452.             return 1;
  2453.         }
  2454.         strcpy(messageDigest1, "whirlpool");
  2455.         evpDigest1 = EVP_get_digestbyname(messageDigest1);
  2456.         if (!evpDigest1) { /*If that's not a valid digest name*/
  2457.             fprintf(stderr, "no such digest\n");
  2458.             return 1;
  2459.         }
  2460.     }
  2461.  
  2462.     return 0;
  2463. }
  2464.  
  2465. int sealEnvelope(const unsigned char* tmpFileToUse)
  2466. {
  2467.     unsigned char cryptoBuffer[BUFFER_SIZES];
  2468.     if (!RAND_bytes(cryptoBuffer, BUFFER_SIZES)) {
  2469.         printf("Failure: CSPRNG bytes could not be made unpredictable\n");
  2470.         cleanUpBuffers();
  2471.         cleanUpFiles();
  2472.         exit(1);
  2473.     }
  2474.     //int EVP1DataSize = returnFileSize(tmpFileToUse);
  2475.  
  2476.     FILE *EVP2DecryptedFile, *EVP1DataFileTmp, *dbFile;
  2477.  
  2478.     /*Generate MAC from EVP1Data written to temp file*/
  2479.     EVP1DataFileTmp = fopen(tmpFileToUse, "rb");
  2480.     if (EVP1DataFileTmp == NULL) {
  2481.         perror("passmanager");
  2482.         return errno;
  2483.     }
  2484.     chmod(tmpFileToUse, S_IRUSR | S_IWUSR);
  2485.  
  2486.     fclose(EVP1DataFileTmp);
  2487.  
  2488.     /*Now append new generated MAC to end of the EVP1 data*/
  2489.     EVP1DataFileTmp = fopen(tmpFileToUse, "ab");
  2490.     if (EVP1DataFileTmp == NULL) /*Make sure the file opens*/
  2491.     {
  2492.         perror("passmanager");
  2493.         return errno;
  2494.     }
  2495.     chmod(tmpFileToUse, S_IRUSR | S_IWUSR);
  2496.  
  2497.     /*Append the MAC and close the file*/
  2498.     returnVal = fwrite(gMac, sizeof(unsigned char), SHA512_DIGEST_LENGTH, EVP1DataFileTmp);
  2499.     if (returnVal != SHA512_DIGEST_LENGTH / sizeof(unsigned char))
  2500.         ;
  2501.     {
  2502.         if (ferror(EVP1DataFileTmp)) {
  2503.             printf("fwrite failed @ 2148\n");
  2504.             return 1;
  2505.         }
  2506.     }
  2507.     fclose(EVP1DataFileTmp);
  2508.  
  2509.     /*Open EVP1 file for reading, so we can use OpenSSL to encrypt it into the final password database file*/
  2510.     EVP2DecryptedFile = fopen(tmpFileToUse, "rb");
  2511.     if (EVP2DecryptedFile == NULL) {
  2512.         perror("passmanager");
  2513.         return errno;
  2514.     }
  2515.     chmod(tmpFileToUse, S_IRUSR | S_IWUSR);
  2516.  
  2517.     /*This will now be an EVP2EncryptedFile but calling it dbFile to clarify it is the final step*/
  2518.     dbFile = fopen(dbFileName, "wb");
  2519.     if (dbFile == NULL) {
  2520.         perror("passmanager");
  2521.         return errno;
  2522.     }
  2523.  
  2524.     /*Write crypto information as a header*/
  2525.  
  2526.     /*Write encCipher:messageDigest to cryptoBuffer*/
  2527.     sprintf(cryptoBuffer, "%s:%s:%s:%s", encCipher1, messageDigest1, encCipher2, messageDigest2);
  2528.  
  2529.     if (toggle.firstRun != 1) {
  2530.         /*Generates a random EVP*_SALT_SIZE byte string into buffer pointed to by saltBuff*/
  2531.         genEvp2Salt();
  2532.     }
  2533.  
  2534.     /*Write the first algorithm's salt*/
  2535.     returnVal = fwrite(evp2Salt, sizeof(unsigned char), EVP2_SALT_SIZE, dbFile);
  2536.     if (returnVal != EVP2_SALT_SIZE / sizeof(unsigned char))
  2537.         ;
  2538.     {
  2539.         if (ferror(dbFile)) {
  2540.             printf("fwrite failed @ 2184\n");
  2541.             return 1;
  2542.         }
  2543.     }
  2544.  
  2545.     /*Write the second algorithm's salt*/
  2546.     returnVal = fwrite(evp1Salt, sizeof(unsigned char), EVP1_SALT_SIZE, dbFile);
  2547.     if (returnVal != EVP1_SALT_SIZE / sizeof(unsigned char))
  2548.         ;
  2549.     {
  2550.         if (ferror(dbFile)) {
  2551.             printf("fwrite failed 2 2192\n");
  2552.             return 1;
  2553.         }
  2554.     }
  2555.  
  2556.     /*Write buffer pointed to by cryptoBuffer*/
  2557.     returnVal = fwrite(cryptoBuffer, sizeof(unsigned char), BUFFER_SIZES, dbFile);
  2558.     if (returnVal != BUFFER_SIZES / sizeof(unsigned char))
  2559.         ;
  2560.     {
  2561.         if (ferror(dbFile)) {
  2562.             printf("fwrite failed @ 2200\n");
  2563.             return 1;
  2564.         }
  2565.     }
  2566.  
  2567.     /*This function generates a key and possibly iv needed for encryption algorithims*/
  2568.  
  2569.     if(evpKDF(dbPass, evp2Salt, EVP2_SALT_SIZE,evpCipher2,evpDigest2,evpKey2,evpIv2) != 0) {
  2570.             return 1;
  2571.     }
  2572.  
  2573.     /*Do the OpenSSL encryption*/
  2574.     if (dbEncrypt(EVP2DecryptedFile, dbFile) != 0) {
  2575.         printf("\\nWrong key used.\n");
  2576.         printf("\nFilename: %s", tmpFile1);
  2577.         return 1;
  2578.     }
  2579.  
  2580.     /*Close the files*/
  2581.     fclose(EVP2DecryptedFile);
  2582.     fclose(dbFile);
  2583.  
  2584.     /*Cleanup temp files*/
  2585.     cleanUpFiles();
  2586.  
  2587.     return 0;
  2588. }
  2589.  
  2590. int openEnvelope()
  2591. {
  2592.     unsigned char cryptoHeader[BUFFER_SIZES];
  2593.     unsigned char* token;
  2594.     //int i;
  2595.  
  2596.     /*a temporary buffer to store the contents of the password file between read and writes to temporary files*/
  2597.     unsigned char* tmpBuffer;
  2598.  
  2599.     /*file handles to be used  for envelope and temporary files*/
  2600.     FILE *EVP2EncryptedFile, *EVP2DecryptedFile, *EVP1DataFileTmp;
  2601.  
  2602.     /*Open the OpenSSL encrypted envelope containing EVP1 Cipher Text +MAC data*/
  2603.     EVP2EncryptedFile = fopen(dbFileName, "rb");
  2604.     if (EVP2EncryptedFile == NULL) /*Make sure the file opens*/
  2605.     {
  2606.         perror("passmanager");
  2607.         return errno;
  2608.     }
  2609.  
  2610.     /*Grab the crypto information from header*/
  2611.     /*This will first contain the EVP2_SALT_SIZE sized salt for evp2Salt*/
  2612.     /*Then an EVP1_SALT_SIZE byte salt for evp1Salt*/
  2613.     /*Then will be the cipher and the message digest names delimited with ':'*/
  2614.  
  2615.     /*fread overwrites the randomly generated salt with the one read from file*/
  2616.     returnVal = fread(evp2Salt, sizeof(unsigned char), EVP2_SALT_SIZE, EVP2EncryptedFile);
  2617.     if (returnVal != EVP2_SALT_SIZE / sizeof(unsigned char)) {
  2618.         if (ferror(EVP2EncryptedFile)) {
  2619.             printf("Fread failed\n");
  2620.             return 1;
  2621.         }
  2622.     }
  2623.  
  2624.     returnVal = fread(evp1Salt, sizeof(unsigned char), EVP1_SALT_SIZE, EVP2EncryptedFile);
  2625.     if (returnVal != EVP1_SALT_SIZE / sizeof(unsigned char)) {
  2626.         if (ferror(EVP2EncryptedFile)) {
  2627.             printf("Fread failed\n");
  2628.             return 1;
  2629.         }
  2630.     }
  2631.  
  2632.     /*Generate a separate salt and key for HMAC authentication*/
  2633.     hmacKDF();
  2634.  
  2635.     /*Read the cipher and message digest information in*/
  2636.     returnVal = fread(cryptoHeader, sizeof(unsigned char), BUFFER_SIZES, EVP2EncryptedFile);
  2637.     if (returnVal != BUFFER_SIZES / sizeof(unsigned char)) {
  2638.         if (ferror(EVP2EncryptedFile)) {
  2639.             printf("Fread failed\n");
  2640.             return 1;
  2641.         }
  2642.     }
  2643.  
  2644.     /*Use strtok to parse the strings delimited by ':'*/
  2645.  
  2646.     /*First the cipher*/
  2647.     token = strtok(cryptoHeader, ":");
  2648.     if (token == NULL) {
  2649.         printf("Could not parse header.\nIs %s a password file?\n", dbFileName);
  2650.         return 1;
  2651.     }
  2652.     strcpy(encCipher1, token);
  2653.  
  2654.     token = strtok(NULL, ":");
  2655.     if (token == NULL) {
  2656.         printf("Could not parse header.\nIs %s a password file?\n", dbFileName);
  2657.         cleanUpFiles();
  2658.         exit(1);
  2659.     }
  2660.  
  2661.     /*Then the message digest*/
  2662.     strcpy(messageDigest1, token);
  2663.  
  2664.     token = strtok(NULL, ":");
  2665.     if (token == NULL) {
  2666.         printf("Could not parse header.\nIs %s a password file?\n", dbFileName);
  2667.         cleanUpFiles();
  2668.         exit(1);
  2669.     }
  2670.  
  2671.     /*Now the 2nd cipher*/
  2672.     strcpy(encCipher2, token);
  2673.  
  2674.     token = strtok(NULL, ":");
  2675.  
  2676.     /*Then the 2nd message digest*/
  2677.     strcpy(messageDigest2, token);
  2678.  
  2679.     /*Check the strings recieved are valid cipher and digest names*/
  2680.     evpCipher1 = EVP_get_cipherbyname(encCipher1);
  2681.     /*If the cipher doesn't exists or there was a problem loading it return with error status*/
  2682.     if (!evpCipher1) {
  2683.         fprintf(stderr, "Could not find valid cipher name in parsed header.\nIs %s a password file?\n", dbFileName);
  2684.         return 1;
  2685.     }
  2686.  
  2687.     evpDigest1 = EVP_get_digestbyname(messageDigest1);
  2688.     if (!evpDigest1) {
  2689.         fprintf(stderr, "Could not find a valid digest name in parsed header.\nIs %s a password file?\n", dbFileName);
  2690.         return 1;
  2691.     }
  2692.  
  2693.     evpCipher2 = EVP_get_cipherbyname(encCipher2);
  2694.     if (!evpCipher2) {
  2695.         fprintf(stderr, "Could not find valid cipher name in parsed header.\nIs %s a password file?\n", dbFileName);
  2696.         return 1;
  2697.     }
  2698.  
  2699.     evpDigest2 = EVP_get_digestbyname(messageDigest2);
  2700.     if (!evpDigest2) {
  2701.         fprintf(stderr, "Could not find a valid digest name in parsed header.\nIs %s a password file?\n", dbFileName);
  2702.         return 1;
  2703.     }
  2704.  
  2705.     /*This function generates a key and possibly iv needed for encryption algorithims*/
  2706.    
  2707.     if(evpKDF(dbPass, evp2Salt, EVP2_SALT_SIZE,evpCipher2,evpDigest2,evpKey2,evpIv2) != 0) {
  2708.             return 1;
  2709.     }
  2710.  
  2711.     if (toggle.updateEncPass) {
  2712.         /*Copy old evpCipher1 to evpCipher1Old and generate evpKey1Old based on this*/
  2713.         /*This needs to be done in openEnvelope() before cipher and digest parameters are changed later on */
  2714.         evpCipher1Old = evpCipher1;
  2715.        
  2716.         if(evpKDF(dbPass, evp1Salt, EVP1_SALT_SIZE,evpCipher1,evpDigest1,evpKey1Old,evpIv1Old) != 0) {
  2717.             return 1;
  2718.         }
  2719.     }
  2720.  
  2721.     /*Now open a temporary file with a randomly generated file name pointed to by tmpFile1*/
  2722.     /*This file will contain the 2nd algorithm's decrypted plain-text, i.e. the 1st algorithm's cipher-text, plus the MAC*/
  2723.     EVP1DataFileTmp = fopen(tmpFile1, "wb");
  2724.     if (EVP1DataFileTmp == NULL) /*Make sure the file opens*/
  2725.     {
  2726.         perror("passmanager");
  2727.         printf("Could not open file: %s", tmpFile1);
  2728.         return errno;
  2729.     }
  2730.     chmod(tmpFile1, S_IRUSR | S_IWUSR);
  2731.  
  2732.     /*Decrypt the OpenSSL envelope file into the aforementioned temp file*/
  2733.     if (dbDecrypt(EVP2EncryptedFile, EVP1DataFileTmp) != 0) {
  2734.         printf("\nWrong key used.\n");
  2735.         fclose(EVP2EncryptedFile);
  2736.         fclose(EVP1DataFileTmp);
  2737.         wipeFile(tmpFile1);
  2738.         remove(tmpFile1);
  2739.         return 1;
  2740.     }
  2741.  
  2742.     /*Now close the encrypted envelope and temp file*/
  2743.     fclose(EVP2EncryptedFile);
  2744.     fclose(EVP1DataFileTmp);
  2745.  
  2746.     /*Open 1st algorithm's cipher-text + MAC from the temporary file*/
  2747.     EVP2DecryptedFile = fopen(tmpFile1, "rb");
  2748.     if (EVP2DecryptedFile == NULL) /*Make sure the file opens*/
  2749.     {
  2750.         perror("passmanager");
  2751.         printf("Could not open file: %s", tmpFile1);
  2752.         return errno;
  2753.     }
  2754.     chmod(tmpFile1, S_IRUSR | S_IWUSR);
  2755.  
  2756.     /*Open a file to write the cipher-text into once we've stripped the MAC off*/
  2757.     EVP1DataFileTmp = fopen(tmpFile2, "wb");
  2758.     if (EVP1DataFileTmp == NULL) /*Make sure the file opens*/
  2759.     {
  2760.         perror("passmanager");
  2761.         return errno;
  2762.     }
  2763.     chmod(tmpFile2, S_IRUSR | S_IWUSR);
  2764.  
  2765.     /*Set EVP2DecryptedFile file position to the beginning of the SHA512_DIGEST_LENGTH sized MAC*/
  2766.  
  2767.     /*Need to get the size of the file, then fseek to that value minus the length SHA512_DIGEST_LENGTH sized MAC*/
  2768.     long fileSize;
  2769.     fseek(EVP2DecryptedFile, 0L, SEEK_END);
  2770.     fileSize = ftell(EVP2DecryptedFile);
  2771.     fseek(EVP2DecryptedFile, fileSize - SHA512_DIGEST_LENGTH, SEEK_SET);
  2772.  
  2773.     /*Read the MAC from EVP2DecryptedFile into buffer pointed to by fMac*/
  2774.     /*fMac for file MAC. Will compare this one against the one generated for gMac*/
  2775.     returnVal = fread(fMac, sizeof(unsigned char), SHA512_DIGEST_LENGTH, EVP2DecryptedFile);
  2776.     if (returnVal != SHA512_DIGEST_LENGTH / sizeof(unsigned char)) {
  2777.         if (ferror(EVP2DecryptedFile)) {
  2778.             printf("Fread failed\n");
  2779.             return 1;
  2780.         }
  2781.     }
  2782.  
  2783.     /*Reset to beginning of the EVP2DecryptedFile file to get ready to copy it to tmpFile2*/
  2784.     fseek(EVP2DecryptedFile, 0L, SEEK_SET);
  2785.  
  2786.     /*Allocate a buffer big enough for the EVP2DecryptedFile file minus the MAC*/
  2787.     tmpBuffer = calloc(sizeof(unsigned char), (fileSize - SHA512_DIGEST_LENGTH));
  2788.  
  2789.     /*Read the cipher-text data into the temp buffer, then write it out to tmpFile2*/
  2790.     returnVal = fread(tmpBuffer, sizeof(unsigned char), fileSize - SHA512_DIGEST_LENGTH, EVP2DecryptedFile);
  2791.     if (returnVal != fileSize - SHA512_DIGEST_LENGTH / sizeof(unsigned char)) {
  2792.         if (ferror(EVP2DecryptedFile)) {
  2793.             printf("Fread failed\n");
  2794.             return 1;
  2795.         }
  2796.     }
  2797.  
  2798.     returnVal = fwrite(tmpBuffer, sizeof(unsigned char), fileSize - SHA512_DIGEST_LENGTH, EVP1DataFileTmp);
  2799.     if (returnVal != fileSize - SHA512_DIGEST_LENGTH / sizeof(unsigned char))
  2800.         ;
  2801.     {
  2802.         if (ferror(EVP1DataFileTmp)) {
  2803.             printf("fwrite failed @ 2411\n");
  2804.             return 1;
  2805.         }
  2806.     }
  2807.  
  2808.     /*Close the temporary files used*/
  2809.     fclose(EVP2DecryptedFile);
  2810.     fclose(EVP1DataFileTmp);
  2811.  
  2812.     /*Erase data left behind in EVP2DecryptedFile*/
  2813.     /*wipeFile() will overwrite the file 25 times with zeroes*/
  2814.     wipeFile(tmpFile1);
  2815.     remove(tmpFile1);
  2816.  
  2817.     free(tmpBuffer);
  2818.  
  2819.     return 0;
  2820. }
  2821.  
  2822. /*Wipes and removes temporary files used*/
  2823. void cleanUpFiles()
  2824. {
  2825.     /*doesFileExist returns 0 if stat() can stat the file*/
  2826.     if (doesFileExist(tmpFile1) == 0) {
  2827.         wipeFile(tmpFile1);
  2828.         remove(tmpFile1);
  2829.     }
  2830.     if (doesFileExist(tmpFile2) == 0) {
  2831.         wipeFile(tmpFile2);
  2832.         remove(tmpFile2);
  2833.     }
  2834.     if (doesFileExist(tmpFile3) == 0) {
  2835.         wipeFile(tmpFile3);
  2836.         remove(tmpFile3);
  2837.     }
  2838. }
  2839.  
  2840. /*Allocate and randomize with OpenSSL's PRNG*/
  2841. void allocateBuffers()
  2842. {
  2843.     entryPass = calloc(sizeof(unsigned char), BUFFER_SIZES);
  2844.     if (!RAND_bytes(entryPass, BUFFER_SIZES)) {
  2845.         printf("Failure: CSPRNG bytes could not be made unpredictable\n");
  2846.         exit(1);
  2847.     }
  2848.  
  2849.     entryPassStore = calloc(sizeof(unsigned char), BUFFER_SIZES);
  2850.     if (!RAND_bytes(entryPassStore, BUFFER_SIZES)) {
  2851.         printf("Failure: CSPRNG bytes could not be made unpredictable\n");
  2852.         exit(1);
  2853.     }
  2854.  
  2855.     entryName = calloc(sizeof(unsigned char), BUFFER_SIZES);
  2856.     if (!RAND_bytes(entryName, BUFFER_SIZES)) {
  2857.         printf("Failure: CSPRNG bytes could not be made unpredictable\n");
  2858.         exit(1);
  2859.     }
  2860.  
  2861.     entryNameToSearch = calloc(sizeof(unsigned char), BUFFER_SIZES);
  2862.     if (!RAND_bytes(entryNameToSearch, BUFFER_SIZES)) {
  2863.         printf("Failure: CSPRNG bytes could not be made unpredictable\n");
  2864.         exit(1);
  2865.     }
  2866.  
  2867.     newEntry = calloc(sizeof(unsigned char), BUFFER_SIZES);
  2868.     if (!RAND_bytes(newEntry, BUFFER_SIZES)) {
  2869.         printf("Failure: CSPRNG bytes could not be made unpredictable\n");
  2870.         exit(1);
  2871.     }
  2872.  
  2873.     newEntryPass = calloc(sizeof(unsigned char), BUFFER_SIZES);
  2874.     if (!RAND_bytes(newEntryPass, BUFFER_SIZES)) {
  2875.         printf("Failure: CSPRNG bytes could not be made unpredictable\n");
  2876.         exit(1);
  2877.     }
  2878.  
  2879.     newEntryPassStore = calloc(sizeof(unsigned char), BUFFER_SIZES);
  2880.     if (!RAND_bytes(newEntryPassStore, BUFFER_SIZES)) {
  2881.         printf("Failure: CSPRNG bytes could not be made unpredictable\n");
  2882.         exit(1);
  2883.     }
  2884.  
  2885.     dbPass = calloc(sizeof(unsigned char), BUFFER_SIZES * 2);
  2886.     if (!RAND_bytes(dbPass, BUFFER_SIZES * 2)) {
  2887.         printf("Failure: CSPRNG bytes could not be made unpredictable\n");
  2888.         exit(1);
  2889.     }
  2890.  
  2891.     dbPassStore = calloc(sizeof(unsigned char), BUFFER_SIZES * 2);
  2892.     if (!RAND_bytes(dbPassStore, BUFFER_SIZES * 2)) {
  2893.         printf("Failure: CSPRNG bytes could not be made unpredictable\n");
  2894.         exit(1);
  2895.     }
  2896.  
  2897.     dbPassOld = calloc(sizeof(unsigned char), BUFFER_SIZES * 2);
  2898.     if (!RAND_bytes(dbPassOld, BUFFER_SIZES * 2)) {
  2899.         printf("Failure: CSPRNG bytes could not be made unpredictable\n");
  2900.         exit(1);
  2901.     }
  2902.  
  2903.     hmacKey = calloc(sizeof(unsigned char), SHA512_DIGEST_LENGTH);
  2904.     if (!RAND_bytes(hmacKey, SHA512_DIGEST_LENGTH)) {
  2905.         printf("Failure: CSPRNG bytes could not be made unpredictable\n");
  2906.         exit(1);
  2907.     }
  2908.  
  2909.     hmacKeyOld = calloc(sizeof(unsigned char), SHA512_DIGEST_LENGTH);
  2910.     if (!RAND_bytes(hmacKeyOld, SHA512_DIGEST_LENGTH)) {
  2911.         printf("Failure: CSPRNG bytes could not be made unpredictable\n");
  2912.         exit(1);
  2913.     }
  2914.  
  2915.     hmacKeyNew = calloc(sizeof(unsigned char), SHA512_DIGEST_LENGTH);
  2916.     if (!RAND_bytes(hmacKeyNew, SHA512_DIGEST_LENGTH)) {
  2917.         printf("Failure: CSPRNG bytes could not be made unpredictable\n");
  2918.         exit(1);
  2919.     }
  2920.  
  2921.     evp1Salt = calloc(sizeof(unsigned char), EVP1_SALT_SIZE);
  2922.     evp2Salt = calloc(sizeof(unsigned char), EVP2_SALT_SIZE);
  2923. }
  2924.  
  2925. /*Fill up the buffers we stored the information in with 0's before exiting*/
  2926. void cleanUpBuffers()
  2927. {
  2928.     OPENSSL_cleanse(entryPass, sizeof(unsigned char) * BUFFER_SIZES);
  2929.     OPENSSL_cleanse(entryName, sizeof(unsigned char) * BUFFER_SIZES);
  2930.     OPENSSL_cleanse(entryNameToSearch, sizeof(unsigned char) * BUFFER_SIZES);
  2931.     OPENSSL_cleanse(newEntry, sizeof(unsigned char) * BUFFER_SIZES);
  2932.     OPENSSL_cleanse(newEntryPass, sizeof(unsigned char) * BUFFER_SIZES);
  2933.     OPENSSL_cleanse(dbPass, sizeof(unsigned char) * strlen(dbPass));
  2934.     OPENSSL_cleanse(dbPassOld, sizeof(unsigned char) * BUFFER_SIZES * 2);
  2935.     OPENSSL_cleanse(evpKey2, sizeof(unsigned char) * EVP_MAX_KEY_LENGTH);
  2936.     OPENSSL_cleanse(evpIv2, sizeof(unsigned char) * EVP_MAX_IV_LENGTH);
  2937.     OPENSSL_cleanse(fMac, sizeof(unsigned char) * SHA512_DIGEST_LENGTH);
  2938.     OPENSSL_cleanse(gMac, sizeof(unsigned char) * SHA512_DIGEST_LENGTH);
  2939. }
  2940.  
  2941. /*This function generates a random passsword if 'gen' is given as the entry's password*/
  2942. void genPassWord(int stringLength)
  2943. {
  2944.     unsigned char b; /*Random byte*/
  2945.     unsigned char tempPassString[stringLength];
  2946.     unsigned i = 0;
  2947.  
  2948.     /*Go until i has iterated over the length of the pass requested*/
  2949.     while (i < stringLength) {
  2950.         /*Gets a random byte from OpenSSL PRNG*/
  2951.         if (!RAND_bytes(&b, 1)) {
  2952.             printf("Failure: CSPRNG bytes could not be made unpredictable\n");
  2953.             cleanUpBuffers();
  2954.             cleanUpFiles();
  2955.             exit(1);
  2956.         }
  2957.  
  2958.         /*Tests that byte to be printable and not blank*/
  2959.         /*If it is it fills the temporary pass string buffer with that byte*/
  2960.         if (toggle.generateEntryPass == 1) {
  2961.             if ((isalnum(b) != 0 || ispunct(b) != 0) && isblank(b) == 0) {
  2962.                 tempPassString[i] = b;
  2963.                 i++;
  2964.             }
  2965.         }
  2966.  
  2967.         if (toggle.generateEntryPassAlpha == 1) {
  2968.             if ((isupper(b) != 0 || islower(b) != 0 || isdigit(b) != 0) && isblank(b) == 0) {
  2969.                 tempPassString[i] = b;
  2970.                 i++;
  2971.             }
  2972.         }
  2973.     }
  2974.  
  2975.     /*Insert a null byte at the end of the randome bytes*/
  2976.     /*Then send that to entryPass*/
  2977.     tempPassString[stringLength] = '\0';
  2978.     strcpy(entryPass, tempPassString);
  2979. }
  2980.  
  2981. unsigned char* genFileName()
  2982. {
  2983.     unsigned char b; /*Random byte*/
  2984.     unsigned char* fileNameBuffer = calloc(sizeof(unsigned char), NAME_MAX);
  2985.     /*Allocate fileName buffer to be large enough to accomodate default temporary directory name*/
  2986.     unsigned char* fileName = calloc(sizeof(unsigned char), NAME_MAX - strlen(P_tmpdir));
  2987.     unsigned i = 0;
  2988.  
  2989.     /*Go until i has iterated over the length of the pass requested*/
  2990.     while (i < NAME_MAX) {
  2991.         /*Gets a random byte from OpenSSL PRNG*/
  2992.         RAND_bytes(&b, 1);
  2993.  
  2994.         /*Tests that byte to be printable and not blank*/
  2995.         /*If it is it fills the temporary pass string buffer with that byte*/
  2996.         if ((isupper(b) != 0 || islower(b) != 0 || isdigit(b) != 0) && isblank(b) == 0) {
  2997.             fileNameBuffer[i] = b;
  2998.             i++;
  2999.         }
  3000.     }
  3001.  
  3002.     /*Add null byte at end of random string generated for filename*/
  3003.     fileNameBuffer[b % (NAME_MAX - strlen(P_tmpdir))] = '\0';
  3004.  
  3005.     /*Preced the sprintf string below with a . to make tmp files write to ./tmp/ for use in testing temp-file attacks*/
  3006.     sprintf(fileName, "%s/%s", P_tmpdir, fileNameBuffer);
  3007.  
  3008.     free(fileNameBuffer);
  3009.  
  3010.     return fileName;
  3011. }
  3012.  
  3013. /*Generates a random EVP2_SALT_SIZE sized byte salt for evpKDF()*/
  3014. void genEvp2Salt()
  3015. {
  3016.  
  3017.     unsigned char b; /*Random byte*/
  3018.     unsigned i = 0;
  3019.  
  3020.     while (i < EVP2_SALT_SIZE) {
  3021.         if (!RAND_bytes(&b, 1)) {
  3022.             printf("Failure: CSPRNG bytes could not be made unpredictable\n");
  3023.             cleanUpBuffers();
  3024.             cleanUpFiles();
  3025.             exit(1);
  3026.             ;
  3027.         }
  3028.         evp2Salt[i] = b;
  3029.         i++;
  3030.     }
  3031. }
  3032.  
  3033. void genEvp1Salt()
  3034. {
  3035.  
  3036.     unsigned char b; /*Random byte*/
  3037.     unsigned int i = 0;
  3038.  
  3039.     while (i < EVP1_SALT_SIZE) {
  3040.         if (!RAND_bytes(&b, 1)) {
  3041.             printf("Failure: CSPRNG bytes could not be made unpredictable\n");
  3042.             cleanUpBuffers();
  3043.             cleanUpFiles();
  3044.             exit(1);
  3045.         }
  3046.         evp1Salt[i] = b;
  3047.         i++;
  3048.     }
  3049. }
  3050.  
  3051. /*Puts an entry's password directly into the clipboard*/
  3052. /*System must have xclip installed*/
  3053. int sendToClipboard(unsigned char* textToSend)
  3054. {
  3055.     unsigned char xclipCommand[] = "xclip -in";
  3056.     unsigned char wipeCommand[] = "xclip -in";
  3057.     unsigned char wipeOutBuffer[strlen(textToSend)];
  3058.     OPENSSL_cleanse(wipeOutBuffer, strlen(textToSend));
  3059.     FILE* xclipFile = popen(xclipCommand, "w");
  3060.     FILE* wipeFile = popen(wipeCommand, "w");
  3061.     pid_t pid, sid;
  3062.  
  3063.     if (xclipFile == NULL) {
  3064.         perror("xclip");
  3065.         return errno;
  3066.     }
  3067.     returnVal = fwrite(textToSend, sizeof(unsigned char), strlen(textToSend), xclipFile);
  3068.     if (returnVal != strlen(textToSend) / sizeof(unsigned char))
  3069.         ;
  3070.     {
  3071.         if (ferror(xclipFile)) {
  3072.             printf("fwrite failed @ 2640\n");
  3073.             return 1;
  3074.         }
  3075.     }
  3076.     if (pclose(xclipFile) == -1) {
  3077.         perror("xclip");
  3078.         return errno;
  3079.     }
  3080.     OPENSSL_cleanse(textToSend, strlen(textToSend));
  3081.  
  3082.     printf("\n%i seconds before password is cleared from clipboard\n", xclipClearTime);
  3083.  
  3084.     /*Going to fork off the application into the background, and wait 30 seconds to send zeroes to the xclip clipboard*/
  3085.     /*This is so that we don't have to contain sensitive information in buffers while we wait*/
  3086.  
  3087.     /*Stops the parent process from waiting for child process to complete*/
  3088.     signal(SIGCHLD, SIG_IGN);
  3089.  
  3090.     /* Fork off the parent process */
  3091.     pid = fork();
  3092.     if (pid < 0) {
  3093.         exit(1);
  3094.     }
  3095.     /* If we got a good PID, then we can exit the parent process. */
  3096.     if (pid > 0) {
  3097.         return 0;
  3098.     }
  3099.  
  3100.     /* At this point we are executing as the child process */
  3101.  
  3102.     /* Create a new SID for the child process */
  3103.     sid = setsid();
  3104.     if (sid < 0) {
  3105.         exit(1);
  3106.     }
  3107.  
  3108.     /*Tells child process to ignore sighup so the child doesn't exit when the parent does*/
  3109.     signal(SIGHUP, SIG_IGN);
  3110.  
  3111.     sid = setsid();
  3112.  
  3113.     sleep(xclipClearTime);
  3114.  
  3115.     returnVal = fwrite(wipeOutBuffer, sizeof(unsigned char), strlen(textToSend), wipeFile);
  3116.     if (returnVal != strlen(textToSend) / sizeof(unsigned char))
  3117.         ;
  3118.     {
  3119.         if (ferror(wipeFile)) {
  3120.             printf("fwrite failed @ 2684\n");
  3121.             return 1;
  3122.         }
  3123.     }
  3124.  
  3125.     exit(0);
  3126. }
  3127.  
  3128. /*Derive a secondary key for HMAC to use*/
  3129. void hmacKDF()
  3130. {
  3131.  
  3132.     int i, originalPassLength;
  3133.     unsigned char hmacSalt[HMAC_SALT_SIZE];
  3134.  
  3135.     /*Derive a larger salt for HMAC from evp1Salt*/
  3136.     /*Use a counter of 3 so this XOR doesn't undo last xor'd bytes*/
  3137.     for (i = 0; i < HMAC_SALT_SIZE; i++)
  3138.         hmacSalt[i] = evp1Salt[i] ^ (i + 3);
  3139.  
  3140.     originalPassLength = strlen(dbPass);
  3141.  
  3142.     /*Generate a separate key to use for HMAC*/
  3143.     PKCS5_PBKDF2_HMAC(dbPass, -1, hmacSalt, HMAC_SALT_SIZE, RFC_2889_REC_ITERATIONS * originalPassLength, EVP_get_digestbyname("sha512"), SHA512_DIGEST_LENGTH, hmacKey);
  3144. }
  3145.  
  3146. int evpKDF(unsigned char* dbPass, unsigned char* evpSalt, unsigned int saltLen,const EVP_CIPHER *evpCipher,const EVP_MD *evpDigest, unsigned char *evpKey, unsigned char *evpIv)
  3147. {
  3148.     /*First generate the key*/
  3149.     if (!PKCS5_PBKDF2_HMAC((unsigned char*)dbPass, strlen(dbPass),
  3150.         evpSalt, saltLen,
  3151.         strlen(dbPass) * RFC_2889_REC_ITERATIONS,
  3152.         evpDigest,EVP_CIPHER_key_length(evpCipher),
  3153.         evpKey)) {
  3154.         fprintf(stderr, "PBKDF2 failed\n");
  3155.         return 1;
  3156.     }
  3157.    
  3158.     /*If this cipher uses an IV, generate that as well*/
  3159.     if(EVP_CIPHER_iv_length(evpCipher) != 0) {
  3160.         if (!PKCS5_PBKDF2_HMAC((unsigned char*)dbPass, strlen(dbPass),
  3161.             evpSalt, saltLen,
  3162.             strlen(dbPass) * RFC_2889_REC_ITERATIONS,
  3163.             evpDigest,EVP_CIPHER_iv_length(evpCipher),
  3164.             evpIv)) {
  3165.         fprintf(stderr, "PBKDF2 failed\n");
  3166.         return 1;
  3167.         }
  3168.     }
  3169.    
  3170.     return 0;
  3171. }
  3172.  
  3173. void signalHandler(int signum)
  3174. {
  3175.     printf("\nCaught signal %d\n\nCleaning up temp files...\nCleaning up buffers...\n", signum);
  3176.     // Cleanup and close up stuff here
  3177.  
  3178.     cleanUpBuffers();
  3179.     cleanUpFiles();
  3180.  
  3181.     /* Restore terminal. */
  3182.     (void)tcsetattr(fileno(stdin), TCSAFLUSH, &termisOld);
  3183.  
  3184.     // Terminate program
  3185.     exit(signum);
  3186. }
  3187.  
  3188. unsigned char* getPass(const char* prompt, char* paddedPass)
  3189. {
  3190.     size_t len = 0;
  3191.     int i;
  3192.     char* pass = NULL;
  3193.  
  3194.  
  3195.     if (!RAND_bytes(paddedPass, BUFFER_SIZES)) {
  3196.         printf("Failure: CSPRNG bytes could not be made unpredictable\n");
  3197.         /* Restore terminal. */
  3198.         (void)tcsetattr(fileno(stdin), TCSAFLUSH, &termisOld);
  3199.         cleanUpBuffers();
  3200.         cleanUpFiles();
  3201.         printf("\nPassword was too large\n");
  3202.         exit(1);
  3203.     }
  3204.     size_t nread;
  3205.  
  3206.     /* Turn echoing off and fail if we can’t. */
  3207.     if (tcgetattr(fileno(stdin), &termisOld) != 0)
  3208.         exit(-1);
  3209.     termiosNew = termisOld;
  3210.     termiosNew.c_lflag &= ~ECHO;
  3211.     if (tcsetattr(fileno(stdin), TCSAFLUSH, &termiosNew) != 0)
  3212.         exit(-1);
  3213.  
  3214.     ///* Read the password. */
  3215.     printf("\n%s", prompt);
  3216.     nread = getline(&pass, &len, stdin);
  3217.     if (nread == -1)
  3218.         exit(1);
  3219.     else if (nread > BUFFER_SIZES) {
  3220.         /* Restore terminal. */
  3221.         (void)tcsetattr(fileno(stdin), TCSAFLUSH, &termisOld);
  3222.         OPENSSL_cleanse(pass, sizeof(char) * nread);
  3223.         free(pass);
  3224.         cleanUpBuffers();
  3225.         cleanUpFiles();
  3226.         printf("\nPassword was too large\n");
  3227.         exit(1);
  3228.     } else {
  3229.         /*Replace newline with null terminator*/
  3230.         pass[nread - 1] = '\0';
  3231.     }
  3232.  
  3233.     /* Restore terminal. */
  3234.     (void)tcsetattr(fileno(stdin), TCSAFLUSH, &termisOld);
  3235.  
  3236.     printf("\n");
  3237.  
  3238.     /*Copy pass into paddedPass then remove sensitive information*/
  3239.     for (i = 0; i < strlen(pass) + 1; i++)
  3240.         paddedPass[i] = pass[i];
  3241.  
  3242.     OPENSSL_cleanse(pass, sizeof(unsigned char) * nread);
  3243.     free(pass);
  3244.  
  3245.     return paddedPass;
  3246. }
  3247.  
  3248. int printMACErrMessage(unsigned char* backupFileName)
  3249. {
  3250.     printf("Message Authentication Failed\nWrong password?\n");
  3251.  
  3252.     return 0;
  3253. }
  3254.  
  3255. int printSyntax(unsigned char* arg)
  3256. {
  3257.     printf("\
  3258. \nReccomend Syntax: \
  3259. \n\n%s [-a entry name | -r entry name | -d entry name | -u entry name [-n new name ] | -U ] [-p new entry password] [-l random password length] [-x database password] [-c first-cipher:second-cipher ] [-H first-digest:second-digest] [ -P ] -f database file [ -C ] [ -s seconds ]\
  3260. \nOptions: \
  3261. \n-n new name - entry name up to 512 characters (can contain white space or special characters) \
  3262. \n-p new entry password - entry password up to 512 characters (don't call to be prompted instead) ('gen' will generate a random password, 'genalpha' will generate a random password with no symbols)\
  3263. \n-l random password length - makes 'gen' or 'genalpha' generate a password random password length digits long (defaults to 16 without this option) \
  3264. \n-x database password - To supply database password as command-line argument (not reccomended) \
  3265. \n-c first-cipher:second-cipher - Specify 'list' for a list of methods available to OpenSSL. Default: camellia-256-ofb:aes-256-ctr. \
  3266. \n-H first-digest:second-digest - Specify 'list' for a list of methods available to OpenSSL. Default: whirlpool:sha512. \
  3267. \n-P - In Update entry or Update database mode (-u and -U respectively) this option enables updating the entry password or database password via prompt instead of as command line argument \
  3268. \n-f - database file ( must be specified ) \
  3269. \n-C - end entry password directly to clipboard. Clipboard is cleared 30 seconds afterward. (needs xclip) \
  3270. \n-s seconds - clear clipboard seconds after instead of default 30 \
  3271. \n-h - Quick usage help \
  3272. \nEach functioning mode has a subset of applicable options \
  3273. \n-a - Add mode \
  3274. \n     \t-p 'password'\
  3275. \n     \t-l 'password length'\
  3276. \n     \t-x 'database password'\
  3277. \n     \t-c 'first-cipher:second-cipher' - Initializes a password database with cascaded encryption of 'first-cipher' into 'second-cipher'\
  3278. \n     \t-H 'first-digest:second-digest' - Derives keys for ciphers with digests 'first-digest' for 'first-cipher' and 'second-digest' for 'second-cipher'.\
  3279. \n     \t-C send new entry's password to clipboard (useful if randomly generated)\
  3280. \n     \t-s seconds - clear clipboard seconds after instead of default 30\
  3281. \n-r - Read mode \
  3282. \n     \t-x 'database password'\
  3283. \n     \t-C  send a specified entry's password directly to clipboard \
  3284. \n     \t-s seconds - clear clipboard seconds after instead of default 30\
  3285. \n-d - Delete mode \
  3286. \n     \t-x 'database password'\
  3287. \n-u - Update entry mode \
  3288. \n     \t-P  updates entry name and password, getting password via user input instead of -p\
  3289. \n     \t-p 'password' - update the entry's password to 'password' \
  3290. \n     \t-l 'password length'\
  3291. \n     \t-n 'entry' - update the entry's name to 'entry'. Without this its assumed you're only changing entry's password. \
  3292. \n     \t-x 'database password'\
  3293. \n     \t-C send entry's new password directly to clipboard\
  3294. \n     \t-s seconds - clear clipboard seconds after instead of default 30\
  3295. \n-U - Update database mode \
  3296. \n     \t-P  updates database password. Read via prompt. Cannot be supplied via commandline. \
  3297. \n     \t-x 'database password' (the current database password to decrypt/with) \
  3298. \n     \t-c 'first-cipher:second-cipher' - Update algorithms in cascade\
  3299. \n     \t-H 'first-digest:second-digest' - Update digests used for cascaded algorithms' KDFs\
  3300. \nVersion 2.2.0\
  3301. \n\
  3302. ",
  3303.         arg);
  3304.     printf("\nThis product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/)\n");
  3305.     return 1;
  3306. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement