Optimizing MD5 OpenSSL Implementation in C for Precomputed Hash
I'll start with a review of your current code before suggesting possible performance
improvements.

Various comments in your code do not add information and can be removed, for example

//------------------------------Main Function------------------------//
int main()

free(string); //free string

exit(EXIT_SUCCESS); //Program Ends




Always use curly braces { } with if-statements, even if the if or else part consists only
of a single statement. That helps to avoid errors if the code is edited later.



Declare variables at the narrowest scope where they are used, and not at the top
of the function. For example

FILE *infile = fopen("file.txt", "r");
if (infile == NULL) {
    exit(EXIT_FAILURE);
}

FILE *outfile = fopen("MD.txt","w");
if (outfile == NULL) {
    exit(EXIT_FAILURE);
}


or

for (int md5 = 0; md5 &lt; MD5_DIGEST_LENGTH; md5++) { ... }


Declaring md5 at the top does not increase the performance.



Some variable names can be improved (of course this is partially opinion-based):


char *string is actually the current line.
size_t len is not the length of the current string,
but the capacity of the buffer (re)allocated by getline(). 
ssize_t read is – strictly speaking – not the number of bytes read into the
buffer because it excludes the NUL character.
int md5 is not an MD5 value but an index into the buffer containing the
MD5 hash.
I would rename unsigned char result[MD5_DIGEST_LENGTH] to md5hash.




Fix compiler warnings:

MD5(string, strlen(string), result);
// Passing 'char *' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign




You already use different exit codes to indicate success or failure of the program,
which is good. In addition, it is helpful to print some message (to standard error)
in the error case.



According to the C11 standard, the declaration of main should be one of

int main(void) { /* ... */ }
int main(int argc, char *argv[]) { /* ... */ }


(see for example What should main() return in C and C++? 
on Stack Overflow). The final return statement can be omitted, there is an implicit
return 0.

Performance improvements

After reading a line from the input file, the string is traversed twice:

while ((read = getline(&amp;string, &amp;len, infile)) != -1) {
    string[strcspn(string, "\n")] = 0; // Remove newline '\n'
    MD5(string, strlen(string), result);

    // ...
}


First to find a terminating newline character, and then again to determine the length.
This is not necessary because getline() returns the number of characters written to
string, i.e. a newline character can only be at position read - 1:

while ((read = getline(&amp;string, &amp;len, infile)) != -1) {
    // Remove trailing newline character
    if (read &gt; 0 &amp;&amp; string[read - 1] == '\n') {
        read -= 1;
        string[read] = 0;
    }

    MD5(string, read, result);

    // ...
}


However, the impact of this change depends on the line length, and I could not observe
a significant difference in my test.

In order to find further performance bottlenecks, I profiled the program now with
Xcode/Instruments (using the input file generated by ./crunch 7 7 1234567890)

This immediately revealed that most of the time is spent in fprintf():



Possible reasons are:


String formatting is slow.
All stdio print operations are thread-safe, and therefore have to aquire and release
locks for each call.


The solution is to:


Write a custom function for converting the MD5 hash to a hex string.
Call printf for the entire string instead of each single byte so reduce the number
of function calls.


On my computer (a 1.2 GHz Intel Core m5 MacBook) this reduced the time for processing
the above file from 24.5 seconds to 4.4 seconds.

Putting it together

With all those modifications, we have

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#include &lt;openssl/md5.h&gt;

// Format the data as a hexadecimal string. The buffer must have
// space for `2 * length + 1` characters.
const char *hexString(unsigned char *data, size_t length, char *buffer) {
    const char *hexDigits = "0123456789abcdef";
    char *dest = buffer;
    for (size_t i = 0; i &lt; length; i++) {
        *dest++ = hexDigits[data[i] &gt;&gt; 4];
        *dest++ = hexDigits[data[i] &amp; 0x0F];
    }
    *dest = 0;
    return buffer;
}

int main(void) {
    FILE *infile = fopen("file.txt", "r");
    if (infile == NULL) {
        perror("Cannot open input file");
        exit(EXIT_FAILURE);
    }
    FILE *outfile = fopen("MD.txt","w");
    if (outfile == NULL) {
        perror("Cannot open output file");
        exit(EXIT_FAILURE);
    }

    // Read file line-by-line
    char *line = NULL;
    size_t linecap = 0;
    ssize_t lineLength;
    while ((lineLength = getline(&amp;line, &amp;linecap, infile)) != -1) {
        if (lineLength &gt; 0 &amp;&amp; line[lineLength - 1] == '\n') {
            // Remove newline character
            lineLength -= 1;
            line[lineLength] = 0;
        }

        // Compute MD5 hash
        unsigned char md5hash[MD5_DIGEST_LENGTH];
        MD5((unsigned char*)line, lineLength, md5hash);

        // Print hash as hex string
        char hexBuffer[2 * MD5_DIGEST_LENGTH + 1];
        fputs(hexString(md5hash, MD5_DIGEST_LENGTH, hexBuffer), outfile);
        fputc('\n', outfile);
    }
    free(line);

    // Close output files
    fclose(infile);
    fclose(outfile);
}


Further suggestions


The names of input and output file are compiled into the program, which makes it inflexible. Possible alternatives are


Pass the file names as arguments on the command line, or
Make your program read from standard input and write to standard output.

Implement a -h option to show a short help/usage of the program.