openssl EVP_CipherFinal_ex failed - c

I got this below function file_encrypt_decrypt for encryption and decryption of a file using AES256 CBC from here.
If I'm doing encryption and decryption both from same program, (main function given at the end) encryption and decryption is working properly. Though both the time same function is called and ctx is initiated again.
If I'm commenting the encryption part, passing the above created encrypted_file, decryption is failing with error:
ERROR: EVP_CipherFinal_ex failed. OpenSSL error: error:06065064:lib(6):func(101):reason(100)
[[meaningful]] OpenSSL error: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
Somewhere people are talking about some padding length issue. But I can't figure it out properly.
Also how the same function is working properly if encryption is done at the same program but separately, it is failing?
Some guidance will be appreciated.
PS: Instead of a common function, I've tried separate functions for encryption and decryption with EVP_DecryptInit_ex(), EVP_DecryptUpdate(), EVP_DecryptFinal_ex() and similar for encryption but of no effect.
Full Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
#define ERR_EVP_CIPHER_INIT -1
#define ERR_EVP_CIPHER_UPDATE -2
#define ERR_EVP_CIPHER_FINAL -3
#define ERR_EVP_CTX_NEW -4
#define AES_256_KEY_SIZE 32
#define AES_BLOCK_SIZE 16
#define BUFSIZE 1024
typedef struct _cipher_params_t{
unsigned char *key;
unsigned char *iv;
unsigned int encrypt;
const EVP_CIPHER *cipher_type;
}cipher_params_t;
void cleanup(cipher_params_t *params, FILE *ifp, FILE *ofp, int rc){
free(params);
fclose(ifp);
fclose(ofp);
exit(rc);
}
void file_encrypt_decrypt(cipher_params_t *params, FILE *ifp, FILE *ofp){
// Allow enough space in output buffer for additional block
int cipher_block_size = EVP_CIPHER_block_size(params->cipher_type);
unsigned char in_buf[BUFSIZE], out_buf[BUFSIZE + cipher_block_size];
int num_bytes_read, out_len;
EVP_CIPHER_CTX *ctx;
ctx = EVP_CIPHER_CTX_new();
if(ctx == NULL){
fprintf(stderr, "ERROR: EVP_CIPHER_CTX_new failed. OpenSSL error: %s\n", ERR_error_string(ERR_get_error(), NULL));
cleanup(params, ifp, ofp, ERR_EVP_CTX_NEW);
}
// Don't set key or IV right away; we want to check lengths
if(!EVP_CipherInit_ex(ctx, params->cipher_type, NULL, NULL, NULL, params->encrypt)){
fprintf(stderr, "ERROR: EVP_CipherInit_ex failed. OpenSSL error: %s\n", ERR_error_string(ERR_get_error(), NULL));
cleanup(params, ifp, ofp, ERR_EVP_CIPHER_INIT);
}
OPENSSL_assert(EVP_CIPHER_CTX_key_length(ctx) == AES_256_KEY_SIZE);
OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) == AES_BLOCK_SIZE);
// Now we can set key and IV
if(!EVP_CipherInit_ex(ctx, NULL, NULL, params->key, params->iv, params->encrypt)){
fprintf(stderr, "ERROR: EVP_CipherInit_ex failed. OpenSSL error: %s\n", ERR_error_string(ERR_get_error(), NULL));
EVP_CIPHER_CTX_cleanup(ctx);
cleanup(params, ifp, ofp, ERR_EVP_CIPHER_INIT);
}
while(1){
// Read in data in blocks until EOF. Update the ciphering with each read.
num_bytes_read = fread(in_buf, sizeof(unsigned char), BUFSIZE, ifp);
if (ferror(ifp)){
fprintf(stderr, "ERROR: fread error: %s\n", strerror(errno));
EVP_CIPHER_CTX_cleanup(ctx);
cleanup(params, ifp, ofp, errno);
}
if(!EVP_CipherUpdate(ctx, out_buf, &out_len, in_buf, num_bytes_read)){
fprintf(stderr, "ERROR: EVP_CipherUpdate failed. OpenSSL error: %s\n", ERR_error_string(ERR_get_error(), NULL));
EVP_CIPHER_CTX_cleanup(ctx);
cleanup(params, ifp, ofp, ERR_EVP_CIPHER_UPDATE);
}
fwrite(out_buf, sizeof(unsigned char), out_len, ofp);
if (ferror(ofp)) {
fprintf(stderr, "ERROR: fwrite error: %s\n", strerror(errno));
EVP_CIPHER_CTX_cleanup(ctx);
cleanup(params, ifp, ofp, errno);
}
if (num_bytes_read < BUFSIZE) {
// Reached End of file
break;
}
}
// Now cipher the final block and write it out to file
if(!EVP_CipherFinal_ex(ctx, out_buf, &out_len)){
fprintf(stderr, "ERROR: EVP_CipherFinal_ex failed. OpenSSL error: %s\n", ERR_error_string(ERR_get_error(), NULL));
EVP_CIPHER_CTX_cleanup(ctx);
cleanup(params, ifp, ofp, ERR_EVP_CIPHER_FINAL);
}
fwrite(out_buf, sizeof(unsigned char), out_len, ofp);
if (ferror(ofp)) {
fprintf(stderr, "ERROR: fwrite error: %s\n", strerror(errno));
EVP_CIPHER_CTX_cleanup(ctx);
cleanup(params, ifp, ofp, errno);
}
EVP_CIPHER_CTX_cleanup(ctx);
}
int main(int argc, char *argv[]) {
FILE *f_input, *f_enc, *f_dec;
// Make sure user provides the input file
if (argc != 2) {
printf("Usage: %s /path/to/file\n", argv[0]);
return -1;
}
cipher_params_t *params = (cipher_params_t *)malloc(sizeof(cipher_params_t));
if (!params) {
// Unable to allocate memory on heap
fprintf(stderr, "ERROR: malloc error: %s\n", strerror(errno));
return errno;
}
// Key to use for encrpytion and decryption
unsigned char key[AES_256_KEY_SIZE];
// Initialization Vector
unsigned char iv[AES_BLOCK_SIZE];
// Generate cryptographically strong pseudo-random bytes for key and IV
if (!RAND_bytes(key, sizeof(key)) || !RAND_bytes(iv, sizeof(iv))) {
// OpenSSL reports a failure, act accordingly
fprintf(stderr, "ERROR: RAND_bytes error: %s\n", strerror(errno));
return errno;
}
params->key = key;
params->iv = iv;
// Indicate that we want to encrypt
params->encrypt = 1;
// Set the cipher type you want for encryption-decryption
params->cipher_type = EVP_aes_256_cbc();
// Open the input file for reading in binary ("rb" mode)
f_input = fopen(argv[1], "rb");
if (!f_input) {
// Unable to open file for reading
fprintf(stderr, "ERROR: fopen error: %s\n", strerror(errno));
return errno;
}
// Open and truncate file to zero length or create ciphertext file for writing
f_enc = fopen("encrypted_file", "wb");
if (!f_enc) {
// Unable to open file for writing
fprintf(stderr, "ERROR: fopen error: %s\n", strerror(errno));
return errno;
}
// Encrypt the given file
file_encrypt_decrypt(params, f_input, f_enc);
// Encryption done, close the file descriptors
fclose(f_input);
fclose(f_enc);
// Decrypt the file
// Indicate that we want to decrypt
params->encrypt = 0;
// Open the encrypted file for reading in binary ("rb" mode)
f_input = fopen("encrypted_file", "rb");
if (!f_input) {
// Unable to open file for reading
fprintf(stderr, "ERROR: fopen error: %s\n", strerror(errno));
return errno;
}
// Open and truncate file to zero length or create decrypted file for writing
f_dec = fopen("decrypted_file", "wb");
if (!f_dec) {
// Unable to open file for writing
fprintf(stderr, "ERROR: fopen error: %s\n", strerror(errno));
return errno;
}
// Decrypt the given file
file_encrypt_decrypt(params, f_input, f_dec);
// Close the open file descriptors
fclose(f_input);
fclose(f_dec);
// Free the memory allocated to our structure
free(params);
return 0;
}

The code generates a new key and a new IV with each run. So if only the encryption part is commented out, then two different key / IV pairs are generated and used for encryption and decryption, which leads to the observed error message. If for testing purposes a fixed key / IV pair is used instead of the each time freshly generated pair, the code works as expected.
In general, the key / IV pair used for encryption must also be used for decryption. Regarding the IV, in practice a random IV is usually generated during encryption. After its use, it's simply added in front of the ciphertext (since the IV isn't secret), so that it can be reconstructed and used during decryption.

Related

Basic recording example using FreeBSD OpenSoundSystem outputs all 0 values

I am trying to implement a basic example to record a few seconds of audio in FreeBSD, which uses a modified OSS version.
Following the sample files included in the FreeBSD source code and the OSS programming guide I have prepared the following sample program:
#include <sys/soundcard.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#define MAX_FILENAME_LENGTH 1024
#define MAX_SECONDS_TO_RECORD 3600 // UP TO 1 HOUR RECORDING
#define MAX_BUFFER_LENGTH 8000*MAX_SECONDS_TO_RECORD
int main(int argc, char *argv[]) {
unsigned char buffer[MAX_BUFFER_LENGTH]; // BUFFER TO STORE AUDIO
char dspfile[MAX_FILENAME_LENGTH]; // /dev/dsp FILENAME
int fd; // /dev/dsp FILE DESCRIPTOR
unsigned int seconds_to_record; // NUMBER OF SECONDS TO RECORD
unsigned long samples_to_record; // NUMBER OF SAMPLES TO RECORD
unsigned long samples_recorded; // NUMBER OF SAMPLES RECORDED
int format; // FORMAT
int channels; // CHANNELS (1=MONO 2=STEREO)
int sampling_rate; // SAMPLING RATE
int error; // AUX VARIABLE ERROR
// STEP 1: READ /dev/dsp PARAMETER
if(argc!=3) {
fprintf(stderr, "ERROR: Incorrect number of arguments.\n");
fprintf(stderr, "USAGE: %s /dev/dsp seconds\n", argv[0]);
exit(1);
} else if( strlen(argv[1]) >= MAX_FILENAME_LENGTH ) {
fprintf(stderr, "ERROR: /dev/dsp filename parameter too long. Maximum size is %d.\n", MAX_FILENAME_LENGTH);
exit(1);
} else {
strncpy(dspfile, argv[1], MAX_FILENAME_LENGTH);
sscanf(argv[2], "%u", &seconds_to_record);
}
if( seconds_to_record >= MAX_SECONDS_TO_RECORD) {
fprintf(stderr, "ERROR: Too many seconds requested. Maximum recording time is %u.\n", MAX_SECONDS_TO_RECORD);
exit(1);
}
// STEP 2: OPEN FILE
fd = open(dspfile, O_RDWR);
if(fd==-1) {
fprintf(stderr, "ERROR: Can not open /dev/dsp file %s. Error code %d %s\n", dspfile, errno, strerror(errno));
exit(1);
}
// STEP 3: CONFIGURE MONO, 8 BITS UNSIGNED SAMPLES, 8KHz SAMPLING RATE
channels = 1;
error = ioctl(fd, SNDCTL_DSP_CHANNELS, &channels);
if(error==-1) {
fprintf(stderr, "ERROR: Can not configure 1 channel. Error code %d %s\n", errno, strerror(errno));
exit(-1);
}
format = AFMT_U8;
error = ioctl(fd, SNDCTL_DSP_SETFMT, &format);
if(error==-1) {
fprintf(stderr, "ERROR: Can not configure audio format. Error code %d %s\n", errno, strerror(errno));
exit(-1);
}
sampling_rate = 8000;
error = ioctl(fd, SNDCTL_DSP_SPEED, &sampling_rate);
if(error==-1) {
fprintf(stderr, "ERROR: Can not configure sampling rate. Error code %d %s\n", errno, strerror(errno));
exit(-1);
}
// STEP 4: RECORD N SAMPLES CORRESPONDING TO THE REQUESTED NUMBER OF SECONDS TO RECORD
samples_to_record = seconds_to_record * 8000;
samples_recorded = 0;
while(samples_to_record > 0) {
ssize_t samples_read = read(fd, buffer + samples_recorded, samples_to_record);
samples_to_record -= (unsigned long)samples_read;
samples_recorded += (unsigned long)samples_read;
write(STDOUT_FILENO, buffer + samples_recorded, samples_read);
}
// STEP 5: CLOSE FILE
if(close(fd)==-1) {
fprintf(stderr, "ERROR: Can not close /dev/dsp file %s. Error code %d %s\n", dspfile, errno, strerror(errno));
exit(1);
}
// DISENGAGE
return(0);
}
But I get a 24000 bytes empty file.
Doing the following works:
cat /dev/dsp > test.raw
cat test.raw > /dev/dsp
So it seems that I am missing something wrong or I am missing one step.

program crashes when encrypting system files

I wrote this code to encrypt and decrypt the contents of folder, both function works well when encrypting normal files but when im changing the folder to system folder, program crashes and when i check the latest file before crashing, im not able to open some of them (File is Open in Another Program), in some of them i just can't make changes.
i'm handling all errors i think, but it still keep crashing when it reachs to opened file by another program, how to solve this problem to ignore these types of files and keep continue instead of crashing?
and the structure is not important to post i think.
char ListFiles(const wchar_t* folder, CIPHER* conf)
{
wchar_t wildcard[MAX_PATH + 1];
swprintf(wildcard, sizeof(wildcard) / sizeof(*wildcard), L"%s\\*", folder);
WIN32_FIND_DATAW fd;
HANDLE handle = FindFirstFileW(wildcard, &fd);
if (handle == INVALID_HANDLE_VALUE) return 1;
do
{
if (wcscmp(fd.cFileName, L".") == 0 || wcscmp(fd.cFileName, L"..") == 0)
continue;
wchar_t path[MAX_PATH + 1];
swprintf(path, sizeof(path) / sizeof(*path), L"%s\\%s", folder, fd.cFileName);
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && !(fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM))
ListFiles(path, &conf);
if (fd.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE && !(fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM))
{
wprintf(L"%s\n", path);
FILE* f_dec;
FILE* f_input = _wfopen(path, L"rb");
FILE* f_enc = _wfopen(wcscat(path, L".encrypted"), L"wb");
if (!f_input || !f_enc) {
fprintf(stderr, "fopen error: %s\n", strerror(errno));
continue;
}
conf->encrypt = 1; // encryption
if (AES_L(conf, f_input, f_enc) != 0)
continue;
f_enc = _wfopen(path, L"rb");
f_dec = _wfopen(wcscat(path, L".decrypted"), L"wb");
if (!f_dec || !f_enc) {
fprintf(stderr, "ERROR: fopen error: %s\n", strerror(errno));
continue;
}
conf->encrypt = 0; // decryption
if (AES_L(conf, f_enc, f_dec) != 0)
continue;
puts("\n\n");
}
} while (FindNextFileW(handle, &fd));
FindClose(handle);
return 0;
}
char AES_L(CIPHER* params, FILE* ifp, FILE* ofp)
{
unsigned int inlen, outlen;
unsigned char* inbuf = (unsigned char*)malloc(params->bufsize);
unsigned char* outbuf = (unsigned char*)malloc(params->bufsize + EVP_MAX_BLOCK_LENGTH);
if (inbuf == NULL || outbuf == NULL)
{
printf("memory cannot be allocated\n");
cleanup(ifp, ofp, inbuf, outbuf);
return 1;
}
EVP_CIPHER_CTX* ctx;
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL) {
fprintf(stderr, "ERROR: EVP_CIPHER_CTX_new failed. OpenSSL error: %s\n",
ERR_error_string(ERR_get_error(), NULL));
cleanup(ifp, ofp, inbuf, outbuf);
return 1;
}
if (!EVP_CipherInit_ex(ctx, params->cipher_type, NULL, params->key, params->iv, params->encrypt)) {
fprintf(stderr, "ERROR: EVP_CipherInit_ex failed. OpenSSL error: %s\n",
ERR_error_string(ERR_get_error(), NULL));
EVP_CIPHER_CTX_cleanup(ctx);
cleanup(ifp, ofp, inbuf, outbuf);
return 1;
}
while (1) {
// Read in data in blocks until EOF. Update the ciphering with each read.
inlen = fread(inbuf, sizeof(*inbuf), params->bufsize, ifp);
if (ferror(ifp)) {
fprintf(stderr, "ERROR: fread error: %s\n", strerror(errno));
EVP_CIPHER_CTX_cleanup(ctx);
cleanup(ifp, ofp, inbuf, outbuf, errno);
return 1;
}
if (!EVP_CipherUpdate(ctx, outbuf, &outlen, inbuf, inlen)) {
fprintf(stderr, "ERROR: EVP_CipherUpdate failed. OpenSSL error: %s\n",
ERR_error_string(ERR_get_error(), NULL));
EVP_CIPHER_CTX_cleanup(ctx);
cleanup(ifp, ofp, inbuf, outbuf);
return 1;
}
fwrite(outbuf, sizeof(*outbuf), outlen, ofp);
if (ferror(ofp)) {
fprintf(stderr, "ERROR: fwrite error: %s\n", strerror(errno));
EVP_CIPHER_CTX_cleanup(ctx);
cleanup(ifp, ofp, inbuf, outbuf, errno);
return 1;
}
if (inlen < params->bufsize) /* Reached End of file */
break;
}
/* Now cipher the final block and write it out to file */
if (!EVP_CipherFinal_ex(ctx, outbuf, &outlen)) {
fprintf(stderr, "ERROR: EVP_CipherFinal_ex failed. OpenSSL error: %s\n",
ERR_error_string(ERR_get_error(), NULL));
EVP_CIPHER_CTX_cleanup(ctx);
cleanup(ifp, ofp, inbuf, outbuf);
return 1;
}
fwrite(outbuf, sizeof(*outbuf), outlen, ofp);
if (ferror(ofp)) {
fprintf(stderr, "ERROR: fwrite error: %s\n", strerror(errno));
EVP_CIPHER_CTX_cleanup(ctx);
cleanup(ifp, ofp, inbuf, outbuf);
return 1;
}
EVP_CIPHER_CTX_cleanup(ctx);
cleanup(ifp, ofp, inbuf, outbuf);
return 0;
}
update:
void cleanup(FILE* ifp, FILE* ofp, unsigned char* inputBuf, unsigned char* outputBuf)
{
free(inputBuf);
free(outputBuf);
fclose(ifp);
fclose(ofp);
}
typedef struct {
unsigned int key_size;
unsigned int block_size;
unsigned int bufsize;
unsigned char* key;
unsigned char* iv;
unsigned int encrypt;
const EVP_CIPHER* cipher_type;
} CIPHER;
I see some problems with your code, although it's hard to know if they can lead to a crash without the rest of the code (for instance, we can't see the cleanup method), or how you create and initialize params.
The first problem is that you may be leaking file handles. When you open the files in ListFiles you open them in pairs, then check if any of them is NULL and if one is, you go on with the loop.
FILE* f_input = _wfopen(path, L"rb");
FILE* f_enc = _wfopen(wcscat(path, L".encrypted"), L"wb");
if (!f_input || !f_enc) {
fprintf(stderr, "fopen error: %s\n", strerror(errno));
continue;
}
What if f_input is opened correctly but f_enc fails? The source file would remain open until the program ends. You should check each of them separately.
A similar problem arises when you allocate memory in AES_L:
unsigned char* inbuf = (unsigned char*)malloc(params->bufsize);
unsigned char* outbuf = (unsigned char*)malloc(params->bufsize + EVP_MAX_BLOCK_LENGTH);
if (inbuf == NULL || outbuf == NULL)
{
printf("memory cannot be allocated\n");
return 1;
}
If one of the buffers (probably inbuf) is allocated correctly but outbuf fails, you would be leaking memory because you don't free the buffer that was allocated correctly (although, to be honest, I don't think this is directly the problem with the crash because this would happen in situations when you are already very low on memory).
Another problem may appear when you create the path for the encrypted and decrypted files. The path buffer is of size MAX_PATH+1, which is enough for the original file name, but then you perform a couple of wcscat operations that lead additional data to be added to the path. What if the original file name was already almost in the MAX_PATH limit? When you performed the wcscat you would be overflowing a buffer in the stack, which may also lead to a crash.
And finally, ListFiles is recursive, so if there are many nested calls you may be running out of stack, which would also lead to a crash (in fact, from the problems I mention I think it's the main suspect). I would make it iterative.
Anyway, it's very difficult to know if the crash is due to these problems, and your best option is running it in the debugger. The error message from the crash will tell you a lot of information to identify the reason.

C: Declaration conflict while using Openssl on cygwin

I want to create a simple program which would encrypt string using RSA algorithm and then decrypt it(cygwin, windows)
Here is my code
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <stdio.h>
#include <string.h>
#define KEY_LENGTH 2048
#define PUB_EXP 3
#define PRINT_KEYS
#define WRITE_TO_FILE
int main(void) {
size_t pri_len; // Length of private key
size_t pub_len; // Length of public key
char *pri_key; // Private key
char *pub_key; // Public key
char msg[KEY_LENGTH/8]; // Message to encrypt
char *encrypt = NULL; // Encrypted message
char *decrypt = NULL; // Decrypted message
char *err; // Buffer for any error messages
// Generate key pair
printf("Generating RSA (%d bits) keypair...", KEY_LENGTH);
fflush(stdout);
RSA *keypair = RSA_generate_key(KEY_LENGTH, PUB_EXP, NULL, NULL);
// To get the C-string PEM form:
BIO *pri = BIO_new(BIO_s_mem());
BIO *pub = BIO_new(BIO_s_mem());
PEM_write_bio_RSAPrivateKey(pri, keypair, NULL, NULL, 0, NULL, NULL);
PEM_write_bio_RSAPublicKey(pub, keypair);
pri_len = BIO_pending(pri);
pub_len = BIO_pending(pub);
pri_key = (char *)malloc(pri_len + 1);
pub_key = (char *)malloc(pub_len + 1);
BIO_read(pri, pri_key, pri_len);
BIO_read(pub, pub_key, pub_len);
pri_key[pri_len] = '\0';
pub_key[pub_len] = '\0';
#ifdef PRINT_KEYS
printf("\n%s\n%s\n", pri_key, pub_key);
#endif
printf("done.\n");
// Get the message to encrypt
printf("Message to encrypt: ");
fgets(msg, KEY_LENGTH-1, stdin);
msg[strlen(msg)-1] = '\0';
// Encrypt the message
encrypt = (char *)malloc(RSA_size(keypair));
int encrypt_len;
err = (char *)malloc(130);
if((encrypt_len = RSA_public_encrypt(strlen(msg)+1, (unsigned char*)msg, (unsigned char*)encrypt,
keypair, RSA_PKCS1_OAEP_PADDING)) == -1) {
ERR_load_crypto_strings();
ERR_error_string(ERR_get_error(), err);
fprintf(stderr, "Error encrypting message: %s\n", err);
return -1;
}
#ifdef WRITE_TO_FILE
// Write the encrypted message to a file
FILE *out = fopen("out.bin", "w");
fwrite(encrypt, sizeof(*encrypt), RSA_size(keypair), out);
fclose(out);
printf("Encrypted message written to file.\n");
free(encrypt);
encrypt = NULL;
// Read it back
printf("Reading back encrypted message and attempting decryption...\n");
encrypt = (char *)malloc(RSA_size(keypair));
out = fopen("out.bin", "r");
fread(encrypt, sizeof(*encrypt), RSA_size(keypair), out);
fclose(out);
#endif
// Decrypt it
decrypt = (char *)malloc(encrypt_len);
if(RSA_private_decrypt(encrypt_len, (unsigned char*)encrypt, (unsigned char*)decrypt,
keypair, RSA_PKCS1_OAEP_PADDING) == -1) {
ERR_load_crypto_strings();
ERR_error_string(ERR_get_error(), err);
fprintf(stderr, "Error decrypting message: %s\n", err);
return -1;
}
printf("Decrypted message: %s\n", decrypt);
RSA_free(keypair);
BIO_free_all(pub);
BIO_free_all(pri);
free(pri_key);
free(pub_key);
free(encrypt);
free(decrypt);
free(err);
return 0;
}
The problem I have is during compiling with command
$ gcc -I /usr/include/ -L /usr/lib/ ip.cpp -o ip.exe -lcrypto.
Here are the errors I have:
In file included from /usr/include/errno.h:9:0,
from /usr/include/openssl/err.h:140,
from ip.cpp:9:
/usr/include/sys/errno.h:14:0: warning: "errno" redefined
#define errno (*__errno())
^
In file included from /usr/lib/gcc/x86_64-w64-mingw32/4.9.2/include/stddef.h:1:0,
from /usr/include/sys/cdefs.h:45,
from /usr/include/time.h:11,
from /usr/include/openssl/asn1.h:62,
from /usr/include/openssl/rsa.h:62,
from ip.cpp:7:
/usr/x86_64-w64-mingw32/sys-root/mingw/include/stddef.h:19:0: note: this is the location of the previous definition
#define errno (*_errno())
^
In file included from /usr/include/sys/select.h:26:0,
from /usr/include/sys/types.h:85,
from /usr/include/time.h:28,
from /usr/include/openssl/asn1.h:62,
from /usr/include/openssl/rsa.h:62,
from ip.cpp:7:
/usr/include/sys/_timeval.h:40:18: error: conflicting declaration ‘typedef long int time_t’
typedef _TIME_T_ time_t;
^
In file included from /usr/x86_64-w64-mingw32/sys-root/mingw/include/stddef.h:7:0,
from /usr/lib/gcc/x86_64-w64-mingw32/4.9.2/include/stddef.h:1,
from /usr/include/sys/cdefs.h:45,
from /usr/include/time.h:11,
from /usr/include/openssl/asn1.h:62,
from /usr/include/openssl/rsa.h:62,
from ip.cpp:7:
/usr/x86_64-w64-mingw32/sys-root/mingw/include/crtdefs.h:138:20: note: previous declaration as ‘typedef __time64_t time_t’
typedef __time64_t time_t;
As you can see the first error is that errno gots defined twice. I checked and in errno.h there is this code:
#ifndef _REENT_ONLY
#define errno (*__errno())
defining _REENT_ONLY fixes this error, but then in stdio.h there is this:
#ifndef _REENT_ONLY
FILE * _EXFUN(fopen, (const char *__restrict _name, const char *__restrict _type));
so then I have fopen undefined error. Plus I don't think that defining some values without really knowing what it is for is a bad idea.
Then I tried manually commenting out the lines where data gets defined second time to just build it successfully and test the program but then I got:
/tmp/ccC3voSz.o:ip.cpp:(.rdata$.refptr._impure_ptr[.refptr._impure_ptr]+0x0): undefined reference to `_impure_ptr'
So at the end I have two problems (maybe they are even related somehow):
How to get rid of the declaration conflicts?
How to fix undefined reference to _impure_ptr

C: Can not decrypt message Openssl

I'm new with cryptography, so I decided to create simple program that would open a file encrypt data, put it in etest.txt, then open this file decrypt it and put it indetest.txt. I know it sounds really weired but its for educational purposes. so here is my code.
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <stdio.h>
#include <string.h>
int main(void) {
size_t pri_len; // Length of private key
size_t pub_len; // Length of public key
char *pri_key; // Private key
char *pub_key; // Public key
char *msg = malloc(256); // Message to encrypt
char *encrypt = NULL; // Encrypted message
char *decrypt = NULL; // Decrypted message
char *err; // Buffer for any error messages
// Generate key pair
RSA *keypair = RSA_generate_key(2048, 3, NULL, NULL);
FILE *in = fopen("test.txt", "rb");
FILE *out = fopen("etest.txt", "wb");
if(in == NULL)
{
printf("in Error is %d (%s).\n", errno, strerror(errno));
}
if(out == NULL)
{
printf("out Error is %d (%s).\n", errno, strerror(errno));
}
encrypt = malloc(RSA_size(keypair));
for(;;)
{
//213 because of padding
memset(msg, '\0', 256);
memset(encrypt, '\0', 256);
fread(msg, 213, 1, in);
if((RSA_public_encrypt(strlen(msg), (unsigned char*)msg, (unsigned char*)encrypt,
keypair, RSA_PKCS1_OAEP_PADDING)) == -1) {
ERR_load_crypto_strings();
ERR_error_string(ERR_get_error(), err);
fprintf(stderr, "Error encrypting message: %s\n", err);
}
if(fwrite(encrypt, 256, 1, out) != 1)
{
printf("fwrite Error is %d (%s).\n", errno, strerror(errno));
}
if(feof(in))
{
break;
}
}
fclose(in);
fclose(out);
in = fopen("etest.txt", "rb");
out = fopen("dtest.txt", "wb");
if(in == NULL)
{
printf("in Error is %d (%s).\n", errno, strerror(errno));
}
if(out == NULL)
{
printf("out Error is %d (%s).\n", errno, strerror(errno));
}
decrypt = malloc(RSA_size(keypair));
for(;;)
{
//I use malloc because if i didnt it would from file and if it filled the msg and if this function would execute second time it would not overwrite the whole buffer and would cause problem
memset(decrypt, '\0', 256);
memset(msg, '\0', 256);
fread(msg, 256, 1, in);
if(RSA_private_decrypt(256, (unsigned char*)msg, (unsigned char*)decrypt,
keypair, RSA_PKCS1_OAEP_PADDING) == -1) {
ERR_load_crypto_strings();
ERR_error_string(ERR_get_error(), err);
fprintf(stderr, "Error decrypting message: %s\n", err);
}
fwrite(decrypt, 256, 1, out);
if(feof(in))
{
break;
}
}
fclose(in);
fclose(out);
RSA_free(keypair);
return 0;
}
When I run code it gives me back error saying:Error decrypting message: error:0407A079:rsa routines:RSA_padding_check_PKCS1_OAEP:oaep decoding error but if i delete this codememset(msg, '\0', 256); it shows that everything works fine but it causes problems because msg buffer is overwritten with first few bytes that second fread() function overwrote.
Sorry if my questions sound silly. Hope you can help. thanks.
Your are using fwrite(decrypt, 256, 1, out); which is wrong.size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) Second parameter is the size in bytes of each element to be read And the third one is number of elements, each one with a size of size bytes.

How to load a PKCS#12 file in OpenSSL programmatically?

In an SSL Server Application based on OpenSSL, how can we load a PKCS#12 file programmatically?
Also, can I load a PKCS#12 file having Certificate, Key & CAs in the same file in OpenSSL?
Yes you can load a PKCS#12 file containing certificate, key and CAs in the same file with OpenSSL.
Use d2i_PKCS12_fp() or d2i_PKCS12_bio() to load the PKCS#12 file.
Optionally use PKCS12_verify_mac() to verify the password.
Use PKCS12_parse() which decrypts and extracts key, certificate and CA chain for you.
From openssl-1.0.0d/demos/pkcs12/pkread.c:
#include <stdio.h>
#include <stdlib.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/pkcs12.h>
/* Simple PKCS#12 file reader */
int main(int argc, char **argv)
{
FILE *fp;
EVP_PKEY *pkey;
X509 *cert;
STACK_OF(X509) *ca = NULL;
PKCS12 *p12;
int i;
if (argc != 4) {
fprintf(stderr, "Usage: pkread p12file password opfile\n");
exit (1);
}
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
if (!(fp = fopen(argv[1], "rb"))) {
fprintf(stderr, "Error opening file %s\n", argv[1]);
exit(1);
}
p12 = d2i_PKCS12_fp(fp, NULL);
fclose (fp);
if (!p12) {
fprintf(stderr, "Error reading PKCS#12 file\n");
ERR_print_errors_fp(stderr);
exit (1);
}
if (!PKCS12_parse(p12, argv[2], &pkey, &cert, &ca)) {
fprintf(stderr, "Error parsing PKCS#12 file\n");
ERR_print_errors_fp(stderr);
exit (1);
}
PKCS12_free(p12);
if (!(fp = fopen(argv[3], "w"))) {
fprintf(stderr, "Error opening file %s\n", argv[1]);
exit(1);
}
if (pkey) {
fprintf(fp, "***Private Key***\n");
PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL);
}
if (cert) {
fprintf(fp, "***User Certificate***\n");
PEM_write_X509_AUX(fp, cert);
}
if (ca && sk_X509_num(ca)) {
fprintf(fp, "***Other Certificates***\n");
for (i = 0; i < sk_X509_num(ca); i++)
PEM_write_X509_AUX(fp, sk_X509_value(ca, i));
}
sk_X509_pop_free(ca, X509_free);
X509_free(cert);
EVP_PKEY_free(pkey);
fclose(fp);
return 0;
}
Be warned that the code writes the certs out as trusted certificates (encrypted).
If you want unencrypted certificates, change the calls to PEM_write_X509_AUX() to PEM_write_X509().
Try man SSL, which gives you a list of OpenSSL functions. Something like SSL_load_client_CA_file might suit your needs; it depends if the certificate is in a file on disk or already in memory. There are lots of helper functions, one of them will do the trick. Also check out man PEM for PEM handling routines.
Edit: Hm, maybe a combination of d2i_PKCS12_fp and PKCS12_parse (both available from <openssl/pkcs12.h>) lets you read a certificate from file and parse it.

Resources