RSA encrypt/decrypt - c

I'm writing a C program that encrypts(based on the private key) and decrypts(based on the public key) text. I'm trying to do this with the OpenSSL lib. Does anyone know any good tutorial, quick starting guide or sample code? I haven't found any decent one on the web.

Here's an example I created for encrypting a file using RSA for the asymmetric algorithm and AES-128-CBC for the symmetric algorithm, with the OpenSSL EVP functions:
#include <stdio.h>
#include <stdlib.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/err.h>
#include <arpa/inet.h> /* For htonl() */
int do_evp_seal(FILE *rsa_pkey_file, FILE *in_file, FILE *out_file)
{
int retval = 0;
RSA *rsa_pkey = NULL;
EVP_PKEY *pkey = EVP_PKEY_new();
EVP_CIPHER_CTX ctx;
unsigned char buffer[4096];
unsigned char buffer_out[4096 + EVP_MAX_IV_LENGTH];
size_t len;
int len_out;
unsigned char *ek = NULL;
int eklen;
uint32_t eklen_n;
unsigned char iv[EVP_MAX_IV_LENGTH];
if (!PEM_read_RSA_PUBKEY(rsa_pkey_file, &rsa_pkey, NULL, NULL))
{
fprintf(stderr, "Error loading RSA Public Key File.\n");
ERR_print_errors_fp(stderr);
retval = 2;
goto out;
}
if (!EVP_PKEY_assign_RSA(pkey, rsa_pkey))
{
fprintf(stderr, "EVP_PKEY_assign_RSA: failed.\n");
retval = 3;
goto out;
}
EVP_CIPHER_CTX_init(&ctx);
ek = malloc(EVP_PKEY_size(pkey));
if (!EVP_SealInit(&ctx, EVP_aes_128_cbc(), &ek, &eklen, iv, &pkey, 1))
{
fprintf(stderr, "EVP_SealInit: failed.\n");
retval = 3;
goto out_free;
}
/* First we write out the encrypted key length, then the encrypted key,
* then the iv (the IV length is fixed by the cipher we have chosen).
*/
eklen_n = htonl(eklen);
if (fwrite(&eklen_n, sizeof eklen_n, 1, out_file) != 1)
{
perror("output file");
retval = 5;
goto out_free;
}
if (fwrite(ek, eklen, 1, out_file) != 1)
{
perror("output file");
retval = 5;
goto out_free;
}
if (fwrite(iv, EVP_CIPHER_iv_length(EVP_aes_128_cbc()), 1, out_file) != 1)
{
perror("output file");
retval = 5;
goto out_free;
}
/* Now we process the input file and write the encrypted data to the
* output file. */
while ((len = fread(buffer, 1, sizeof buffer, in_file)) > 0)
{
if (!EVP_SealUpdate(&ctx, buffer_out, &len_out, buffer, len))
{
fprintf(stderr, "EVP_SealUpdate: failed.\n");
retval = 3;
goto out_free;
}
if (fwrite(buffer_out, len_out, 1, out_file) != 1)
{
perror("output file");
retval = 5;
goto out_free;
}
}
if (ferror(in_file))
{
perror("input file");
retval = 4;
goto out_free;
}
if (!EVP_SealFinal(&ctx, buffer_out, &len_out))
{
fprintf(stderr, "EVP_SealFinal: failed.\n");
retval = 3;
goto out_free;
}
if (fwrite(buffer_out, len_out, 1, out_file) != 1)
{
perror("output file");
retval = 5;
goto out_free;
}
out_free:
EVP_PKEY_free(pkey);
free(ek);
out:
return retval;
}
int main(int argc, char *argv[])
{
FILE *rsa_pkey_file;
int rv;
if (argc < 2)
{
fprintf(stderr, "Usage: %s <PEM RSA Public Key File>\n", argv[0]);
exit(1);
}
rsa_pkey_file = fopen(argv[1], "rb");
if (!rsa_pkey_file)
{
perror(argv[1]);
fprintf(stderr, "Error loading PEM RSA Public Key File.\n");
exit(2);
}
rv = do_evp_seal(rsa_pkey_file, stdin, stdout);
fclose(rsa_pkey_file);
return rv;
}
And the corresponding decryption example:
#include <stdio.h>
#include <stdlib.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/err.h>
#include <arpa/inet.h> /* For htonl() */
int do_evp_unseal(FILE *rsa_pkey_file, FILE *in_file, FILE *out_file)
{
int retval = 0;
RSA *rsa_pkey = NULL;
EVP_PKEY *pkey = EVP_PKEY_new();
EVP_CIPHER_CTX ctx;
unsigned char buffer[4096];
unsigned char buffer_out[4096 + EVP_MAX_IV_LENGTH];
size_t len;
int len_out;
unsigned char *ek;
unsigned int eklen;
uint32_t eklen_n;
unsigned char iv[EVP_MAX_IV_LENGTH];
if (!PEM_read_RSAPrivateKey(rsa_pkey_file, &rsa_pkey, NULL, NULL))
{
fprintf(stderr, "Error loading RSA Private Key File.\n");
ERR_print_errors_fp(stderr);
retval = 2;
goto out;
}
if (!EVP_PKEY_assign_RSA(pkey, rsa_pkey))
{
fprintf(stderr, "EVP_PKEY_assign_RSA: failed.\n");
retval = 3;
goto out;
}
EVP_CIPHER_CTX_init(&ctx);
ek = malloc(EVP_PKEY_size(pkey));
/* First need to fetch the encrypted key length, encrypted key and IV */
if (fread(&eklen_n, sizeof eklen_n, 1, in_file) != 1)
{
perror("input file");
retval = 4;
goto out_free;
}
eklen = ntohl(eklen_n);
if (eklen > EVP_PKEY_size(pkey))
{
fprintf(stderr, "Bad encrypted key length (%u > %d)\n", eklen,
EVP_PKEY_size(pkey));
retval = 4;
goto out_free;
}
if (fread(ek, eklen, 1, in_file) != 1)
{
perror("input file");
retval = 4;
goto out_free;
}
if (fread(iv, EVP_CIPHER_iv_length(EVP_aes_128_cbc()), 1, in_file) != 1)
{
perror("input file");
retval = 4;
goto out_free;
}
if (!EVP_OpenInit(&ctx, EVP_aes_128_cbc(), ek, eklen, iv, pkey))
{
fprintf(stderr, "EVP_OpenInit: failed.\n");
retval = 3;
goto out_free;
}
while ((len = fread(buffer, 1, sizeof buffer, in_file)) > 0)
{
if (!EVP_OpenUpdate(&ctx, buffer_out, &len_out, buffer, len))
{
fprintf(stderr, "EVP_OpenUpdate: failed.\n");
retval = 3;
goto out_free;
}
if (fwrite(buffer_out, len_out, 1, out_file) != 1)
{
perror("output file");
retval = 5;
goto out_free;
}
}
if (ferror(in_file))
{
perror("input file");
retval = 4;
goto out_free;
}
if (!EVP_OpenFinal(&ctx, buffer_out, &len_out))
{
fprintf(stderr, "EVP_SealFinal: failed.\n");
retval = 3;
goto out_free;
}
if (fwrite(buffer_out, len_out, 1, out_file) != 1)
{
perror("output file");
retval = 5;
goto out_free;
}
out_free:
EVP_PKEY_free(pkey);
free(ek);
out:
return retval;
}
int main(int argc, char *argv[])
{
FILE *rsa_pkey_file;
int rv;
if (argc < 2)
{
fprintf(stderr, "Usage: %s <PEM RSA Private Key File>\n", argv[0]);
exit(1);
}
rsa_pkey_file = fopen(argv[1], "rb");
if (!rsa_pkey_file)
{
perror(argv[1]);
fprintf(stderr, "Error loading PEM RSA Private Key File.\n");
exit(2);
}
rv = do_evp_unseal(rsa_pkey_file, stdin, stdout);
fclose(rsa_pkey_file);
return rv;
}
I think that's fairly easy to follow. As written both commands can be used as part of a pipeline (they take input on stdin and write output to stdout).

Related

SegFault in read function for serial device

I'm attempting to interface with a measurement device through serial. I have already created one successful program that works and does what I want, but it doesn't have live user input.
My problem comes from a program I'm creating where I want to make a live serial terminal to interact with the device. In this program I have the user type the commands to the machine and for some commands the machine has to return a 1 or 0. This is where the problem comes. In the live environment, when I read a 1 after a command I get a segfault.
This is the segment that deals with commands that require the machine to send a 1 or 0.
buf = malloc(1);
if (buf == NULL)
{
perror("memory error");
goto fail;
}
...
if (write == 0)
{
for (i = 0; i < read_com.num; i++)
{
if (strcmp(buff, read_com.check[i]) == 0)
{
ret = write_port(fd, buff, strlen(buff));
if (ret < 0)
goto fail;
ret = read_port(fd, buf, 1);
if (ret < 0)
goto fail;
printf("Read success");
write = 1;
break;
}
}
}
This is the read port function where the segfault is occurring
int read_port(int fd, char *buf, const size_t size)
{
ssize_t r;
size_t received;
received = 0;
while (received < size)
{
r = read(fd, buf + received, size - received);
if (r < 0)
{
perror("failed to read from port");
return -1;
}
if (r == 0)
{
break;
}
received += r;
}
return received;
}
All code below:
live.c:
#include "GPIB_prof.h"
#include "serial.h"
#include "commands.h"
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
const struct com read_com = {3, {"OPC?;PRES;\r", "OPC?;WAIT;\r", "CORRON;\r"}};
const struct com numc = {3, {"STAR", "STOP", "POIN"}};
int main(int argc, char *argv[])
{
int fd;
int ret;
char *buff;
char *buf;
int i;
bool write = 0;
int fin = 0;
char *numb;
char *rem;
int star;
int stop;
int poin;
char *dat;
int fc = 0;
char *file;
FILE *temp;
FILE *f;
rem = malloc(256);
if (rem == NULL)
{
perror("memory error");
goto fail;
}
numb = malloc(4);
if (numb == NULL)
{
perror("memory error");
goto fail;
}
buff = malloc(256);
if (buff == NULL)
{
perror("memory error");
goto fail;
}
buf = malloc(1);
if (buf == NULL)
{
perror("memory error");
goto fail;
}
file = malloc(5);
if (file == NULL)
{
perror("memory error");
goto fail;
}
if (argc < 3)
{
printf("Usage: %s [serial device] [baud rate]", argv[0]);
goto fail;
}
fd = open_port(argv[1], atoi(argv[2]));
if (fd < 0)
goto fail;
ret = GPIB_conf(fd, 0);
if (ret < 0)
goto fail;
while (fin == 0)
{
write = 0;
scanf("%s", buff);
strcat(buff, "\r");
//if (ret<0) goto fail;
for (i = 0; i < strlen(buff); i++)
{
if (i < 4)
{
numb[i] = buff[i];
}
else
{
rem[i - 4] = buff[i];
}
}
if (strcmp(numb, "OUTP") == 0)
{
ret = write_port(fd, buff, strlen(buff));
if (ret < 0)
goto fail;
write = 1;
ret = read_port(fd, dat, 50 * poin);
if (ret < 0)
goto fail;
else
goto data;
}
if (write == 0)
{
for (i = 0; i < read_com.num; i++)
{
if (strcmp(buff, read_com.check[i]) == 0)
{
ret = write_port(fd, buff, strlen(buff));
if (ret < 0)
goto fail;
ret = read_port(fd, buf, 1);
if (ret < 0)
goto fail;
printf("Read success");
write = 1;
break;
}
}
}
if (write == 0)
{
for (i = 0; i < numc.num; i++)
{
if (strcmp(numb, numc.check[i]) == 0)
{
ret = write_port(fd, buff, strlen(buff));
if (ret < 0)
goto fail;
write = 1;
if (strcmp(numb, "STAR") == 0)
{
star = atoi(rem);
}
else if (strcmp(numb, "STOP") == 0)
{
stop = atoi(rem);
}
else if (strcmp(numb, "POIN") == 0)
{
poin = atoi(rem);
dat = malloc(50 * poin);
if (dat == NULL)
{
perror("memory error");
goto fail;
}
fc++;
}
break;
}
}
if (write == 0)
{
ret = write_port(fd, buff, strlen(buff));
if (ret < 0)
goto fail;
write = 1;
}
}
}
printf("Start freq: %d\nStop freq: %d\n", star, stop);
free(rem);
free(numb);
free(buff);
free(buf);
free(file);
free(dat);
return 0;
data:
ret = sprintf(file, "data%d", fc);
if (ret < 0)
goto fail;
temp = fopen(file, "w+");
if (temp == NULL)
{
perror("failed to open file");
fclose(temp);
goto fail;
}
fclose(temp);
ret = remove(file);
if (ret != 0)
{
perror("failed to remove file");
goto fail;
}
f = fopen(file, "w");
if (f == NULL)
{
perror("failed to open file");
fclose(f);
goto fail;
}
for (i = 0; i < (50 * poin); i++)
{
ret = fprintf(f, "%c", dat[i]);
if (ret < 0)
{
fclose(f);
goto fail;
}
}
fclose(f);
fin++;
fail:
free(rem);
free(numb);
free(buff);
free(buf);
free(file);
free(dat);
return -1;
}
serial.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <stdint.h>
#include <unistd.h>
#include "serial.h"
#include "GPIB_prof.h"
struct termios options;
int open_port(const char *dev, uint32_t baud)
{
int fd;
int ret;
char *baud_f;
struct termios opt;
baud_f = malloc(8 * sizeof(char));
if (baud_f == NULL)
{
perror("memory error");
goto fail;
}
fd = open(dev, O_RDWR, 0777);
if (fd < 0)
{
perror(dev);
goto fail;
}
ret = tcflush(fd, TCIOFLUSH);
if (ret)
{
perror("tcgetattr failed");
goto fail;
}
opt.c_cflag = (opt.c_cflag & ~CSIZE) | CS8;
opt.c_cflag &= ~IGNBRK;
opt.c_lflag = 0;
opt.c_oflag = 0;
opt.c_cc[VTIME] = 5;
opt.c_cc[VMIN] = 1;
opt.c_iflag &= ~(IXON | IXOFF | IXANY);
opt.c_cflag |= (CLOCAL | CREAD);
opt.c_cflag &= ~(PARENB | PARODD);
opt.c_cflag |= 0;
opt.c_cflag &= ~CSTOPB;
ret = sprintf(baud_f, "B%d", baud);
if (ret < 0)
{
perror("memory error");
goto fail;
}
baud = (uintptr_t)baud_f;
cfsetospeed(&opt, baud);
cfsetispeed(&opt, baud);
ret = tcsetattr(fd, TCSANOW, &opt);
if (ret)
{
perror("tcsetarre failed");
goto fail;
}
free(baud_f);
return fd;
fail:
free(baud_f);
close(fd);
return -1;
}
int read_port(int fd, char *buf, const size_t size)
{
ssize_t r;
size_t received;
received = 0;
while (received < size)
{
r = read(fd, buf + received, size - received);
if (r < 0)
{
perror("failed to read from port");
return -1;
}
if (r == 0)
{
break;
}
received += r;
}
return received;
}
int write_port(int fd, const char *buf, const size_t size)
{
ssize_t res;
res = write(fd, buf, size);
if (res != (ssize_t)size)
{
perror("failed to write to port");
return -1;
}
usleep(size * 100);
return 0;
}
int GPIB_conf(int fd, int profile)
{
int ret;
switch (profile)
{
case 0:
ret = def(fd);
if (ret < 0)
goto fail;
}
return 0;
fail:
return -1;
}
serial.h
#ifndef _SERIAL_H_
#define _SERIAL_H_
#include <stdint.h>
#include <stddef.h>
#include "GPIB_prof.h"
int open_port (const char *dev, uint32_t baud);
int read_port (int fd, char *buf, size_t size);
int write_port (int fd, const char *buf, size_t size);
int GPIB_conf (int fd, int profile);
#endif
commands.h:
#ifndef _COMMANDS_H_
#define _COMMANDS_H_
struct com
{
const int num;
const char *check[];
};
#endif
GPIB_prof.c:
#include "GPIB_prof.h"
#include "serial.h"
int def(int fd)
{
int ret;
ret = write_port(fd, "++mode 1\r", 9);
if (ret < 0)
goto fail;
ret = write_port(fd, "++addr 16\r", 10);
if (ret < 0)
goto fail;
ret = write_port(fd, "++eoi 0\r", 8);
if (ret < 0)
goto fail;
ret = write_port(fd, "++eot_enable 1\r", 15);
if (ret < 0)
goto fail;
ret = write_port(fd, "++eot_char 13\r", 14);
if (ret < 0)
goto fail;
ret = write_port(fd, "++ifc\r", 6);
if (ret < 0)
goto fail;
ret = write_port(fd, "++auto 1\r", 9);
if (ret < 0)
goto fail;
return 0;
fail:
return -1;
}
GPIB_prof.h:
#ifndef _PROFILE_H_
#define _PROFILE_H_
int def(int fd);
#endif
Caveat: This may not be a total solution as there are many compiler warnings for possibly uninitialized variables, etc.
Note that I'd rename some variables. You have a global called read. That tends to conflict with the standard read function. (i.e.) don't define functions/variables that conflict with standard functions/variables: caveat emptor.
Here is the compiler output I get for (e.g.) cc -o orig orig.c -Wall -Wextra -O2.
Notably, a number of pointer variables may have uninitialized values. This really should be restructured and the warnings fixed as the code is fragile and the compiler is pointing out things that could easily explain your runtime error(s).
orig.c: In function ‘GPIB_conf’:
orig.c:136:15: warning: unused parameter ‘fd’ [-Wunused-parameter]
GPIB_conf(int fd, int profile)
~~~~^~
orig.c: In function ‘main’:
orig.c:217:17: warning: comparison of integer expressions of different signedness: ‘int’ and ‘size_t’ {aka ‘long unsigned int’} [-Wsign-compare]
for (i = 0; i < strlen(buff); i++) {
^
orig.c:325:5: warning: increment of a boolean expression [-Wbool-operation]
fin++;
^~
orig.c: In function ‘open_port’:
orig.c:96:2: warning: ‘fd’ may be used uninitialized in this function [-Wmaybe-uninitialized]
close(fd);
^~~~~~~~~
orig.c: In function ‘main’:
orig.c:295:27: warning: ‘%d’ directive writing between 1 and 10 bytes into a region of size 1 [-Wformat-overflow=]
ret = sprintf(file, "data%d", fc);
^~
orig.c:295:22: note: directive argument in the range [0, 2147483647]
ret = sprintf(file, "data%d", fc);
^~~~~~~~
orig.c:295:8: note: ‘sprintf’ output between 6 and 15 bytes into a destination of size 5
ret = sprintf(file, "data%d", fc);
^~~~~~~~~~~~~~~~~~~~~~~~~~~
orig.c:332:2: warning: ‘file’ may be used uninitialized in this function [-Wmaybe-uninitialized]
free(file);
^~~~~~~~~~
orig.c:333:2: warning: ‘dat’ may be used uninitialized in this function [-Wmaybe-uninitialized]
free(dat);
^~~~~~~~~
orig.c:329:2: warning: ‘numb’ may be used uninitialized in this function [-Wmaybe-uninitialized]
free(numb);
^~~~~~~~~~
orig.c:331:2: warning: ‘buf’ may be used uninitialized in this function [-Wmaybe-uninitialized]
free(buf);
^~~~~~~~~
orig.c:330:2: warning: ‘buff’ may be used uninitialized in this function [-Wmaybe-uninitialized]
free(buff);
^~~~~~~~~~
orig.c:230:32: warning: ‘poin’ may be used uninitialized in this function [-Wmaybe-uninitialized]
ret = read_port(fd, dat, 50 * poin);
~~~^~~~~~
I had to refactor/nop some of the code to get it to compile without the full definitions in the [missing] .h files. However, these hacks do not account for the warnings above.
#include "GPIB_prof.h"
#include "serial.h"
#include "commands.h"
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#define def(_fd) \
0
struct com {
int num;
char *check[3];
};
const struct com read_com = { 3, {"OPC?;PRES;\r", "OPC?;WAIT;\r", "CORRON;\r"} };
const struct com numc = { 3, {"STAR", "STOP", "POIN"} };
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <stdint.h>
#include <unistd.h>
#include "serial.h"
#include "GPIB_prof.h"
struct termios options;
int
open_port(const char *dev, uint32_t baud)
{
int fd;
int ret;
char *baud_f;
struct termios opt;
baud_f = malloc(8 * sizeof(char));
if (baud_f == NULL) {
perror("memory error");
goto fail;
}
fd = open(dev, O_RDWR, 0777);
if (fd < 0) {
perror(dev);
goto fail;
}
ret = tcflush(fd, TCIOFLUSH);
if (ret) {
perror("tcgetattr failed");
goto fail;
}
opt.c_cflag = (opt.c_cflag & ~CSIZE) | CS8;
opt.c_cflag &= ~IGNBRK;
opt.c_lflag = 0;
opt.c_oflag = 0;
opt.c_cc[VTIME] = 5;
opt.c_cc[VMIN] = 1;
opt.c_iflag &= ~(IXON | IXOFF | IXANY);
opt.c_cflag |= (CLOCAL | CREAD);
opt.c_cflag &= ~(PARENB | PARODD);
opt.c_cflag |= 0;
opt.c_cflag &= ~CSTOPB;
ret = sprintf(baud_f, "B%d", baud);
if (ret < 0) {
perror("memory error");
goto fail;
}
baud = (uintptr_t) baud_f;
cfsetospeed(&opt, baud);
cfsetispeed(&opt, baud);
ret = tcsetattr(fd, TCSANOW, &opt);
if (ret) {
perror("tcsetarre failed");
goto fail;
}
free(baud_f);
return fd;
fail:
free(baud_f);
close(fd);
return -1;
}
int
read_port(int fd, char *buf, const size_t size)
{
ssize_t r;
size_t received;
received = 0;
while (received < size) {
r = read(fd, buf + received, size - received);
if (r < 0) {
perror("failed to read from port");
return -1;
}
if (r == 0) {
break;
}
received += r;
}
return received;
}
int
write_port(int fd, const char *buf, const size_t size)
{
ssize_t res;
res = write(fd, buf, size);
if (res != (ssize_t) size) {
perror("failed to write to port");
return -1;
}
usleep(size * 100);
return 0;
}
int
GPIB_conf(int fd, int profile)
{
int ret;
switch (profile) {
case 0:
ret = def(fd);
if (ret < 0)
goto fail;
}
return 0;
fail:
return -1;
}
int
main(int argc, char *argv[])
{
int fd;
int ret;
char *buff;
char *buf;
int i;
bool write = 0;
bool fin = 0;
char *numb;
char *rem;
int star;
int stop;
int poin;
char *dat;
int fc = 0;
char *file;
FILE *temp;
FILE *f;
rem = malloc(256);
if (rem == NULL) {
perror("memory error");
goto fail;
}
numb = malloc(4);
if (numb == NULL) {
perror("memory error");
goto fail;
}
buff = malloc(256);
if (buff == NULL) {
perror("memory error");
goto fail;
}
buf = malloc(1);
if (buf == NULL) {
perror("memory error");
goto fail;
}
file = malloc(5);
if (file == NULL) {
perror("memory error");
goto fail;
}
if (argc < 3) {
printf("Usage: %s [serial device] [baud rate]", argv[0]);
goto fail;
}
fd = open_port(argv[1], atoi(argv[2]));
if (fd < 0)
goto fail;
ret = GPIB_conf(fd, 0);
if (ret < 0)
goto fail;
while (fin == 0) {
write = 0;
scanf("%s", buff);
strcat(buff, "\r");
// if (ret<0) goto fail;
for (i = 0; i < strlen(buff); i++) {
if (i < 4) {
numb[i] = buff[i];
}
else {
rem[i - 4] = buff[i];
}
}
if (strcmp(numb, "OUTP") == 0) {
ret = write_port(fd, buff, strlen(buff));
if (ret < 0)
goto fail;
write = 1;
ret = read_port(fd, dat, 50 * poin);
if (ret < 0)
goto fail;
else
goto data;
}
if (write == 0) {
for (i = 0; i < read_com.num; i++) {
if (strcmp(buff, read_com.check[i]) == 0) {
ret = write_port(fd, buff, strlen(buff));
if (ret < 0)
goto fail;
ret = read_port(fd, buf, 1);
if (ret < 0)
goto fail;
printf("Read success");
write = 1;
break;
}
}
}
if (write == 0) {
for (i = 0; i < numc.num; i++) {
if (strcmp(numb, numc.check[i]) == 0) {
ret = write_port(fd, buff, strlen(buff));
if (ret < 0)
goto fail;
write = 1;
if (strcmp(numb, "STAR") == 0) {
star = atoi(rem);
}
else if (strcmp(numb, "STOP") == 0) {
stop = atoi(rem);
}
else if (strcmp(numb, "POIN") == 0) {
poin = atoi(rem);
dat = malloc(50 * poin);
if (dat == NULL) {
perror("memory error");
goto fail;
}
fc++;
}
break;
}
}
if (write == 0) {
ret = write_port(fd, buff, strlen(buff));
if (ret < 0)
goto fail;
write = 1;
}
}
}
printf("Start freq: %d\nStop freq: %d\n", star, stop);
free(rem);
free(numb);
free(buff);
free(buf);
free(file);
free(dat);
return 0;
data:
ret = sprintf(file, "data%d", fc);
if (ret < 0)
goto fail;
temp = fopen(file, "w+");
if (temp == NULL) {
perror("failed to open file");
fclose(temp);
goto fail;
}
fclose(temp);
ret = remove(file);
if (ret != 0) {
perror("failed to remove file");
goto fail;
}
f = fopen(file, "w");
if (f == NULL) {
perror("failed to open file");
fclose(f);
goto fail;
}
for (i = 0; i < (50 * poin); i++) {
ret = fprintf(f, "%c", dat[i]);
if (ret < 0) {
fclose(f);
goto fail;
}
}
fclose(f);
fin++;
fail:
free(rem);
free(numb);
free(buff);
free(buf);
free(file);
free(dat);
return -1;
}

Unable to decrypt: RSA_R_PADDING_CHECK_FAILED - OpenSSL 1.1.0‏

I'm creating a simple utility to encrypt and decrypt files using a key pair. I'm on Windows and coding against the 1.1.0 version of Openssl. I can load the key pair and encrypt the file fine, but when I try to decrypt EVP_PKEY_decrypt always returns -1. I traced this to the rsa padding check functions and they are returning -1 but I can't figure out why. I've tried changing the padding from RSA_PKCS1_OAEP_PADDING to RSA_PKCS1_PADDING and still have the same problem. Any insight would be appreciated, here are my encrypt and decrypt functions:
#define FILE_BUFFER_LENGTH 1
#define ENC_BUFFER_LENGTH 2048
int encryptfile(EVP_PKEY *key, FILE *srcfp, FILE *tgtfp) {
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(key, NULL);
char *inbuf;
unsigned char *outbuf;
size_t in_len = 0;
size_t out_len = ENC_BUFFER_LENGTH;
int x;
inbuf = (char*)malloc(sizeof(char)*FILE_BUFFER_LENGTH+1);
outbuf = (char*)malloc(sizeof(char)*ENC_BUFFER_LENGTH+1);
if (ctx == NULL) {
fprintf(stderr, "Error while creating encryption context.\n");
return 0;
}
if (EVP_PKEY_encrypt_init(ctx) <= 0) {
fprintf(stderr, "Error while initializing encryption context.\n");
return 0;
}
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) {
fprintf(stderr, "Error while setting encryption padding.\n");
return 0;
}
while (1) {
in_len = fread(inbuf, 1, FILE_BUFFER_LENGTH, srcfp);
if (in_len == 0) {break;}
if (EVP_PKEY_encrypt(ctx, outbuf, &out_len, inbuf, in_len) <= 0) {
fprintf(stderr, "Error while encrypting data.\n");
return 0;
}
x = fwrite(outbuf, sizeof(char), in_len, tgtfp);
if (x != in_len) {
fprintf(stderr, "Error while writing to target file.\n");
return 0;
}
}
return 1;
}
int decryptfile(EVP_PKEY *key, FILE *srcfp, FILE *tgtfp) {
ENGINE *e = ENGINE_new();
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(key, NULL);
unsigned char *inbuf;
unsigned char *outbuf;
size_t in_len = 0;
size_t out_len = ENC_BUFFER_LENGTH;
int x;
inbuf = (char*)malloc(sizeof(char)*FILE_BUFFER_LENGTH + 1);
outbuf = (char*)malloc(sizeof(char)*ENC_BUFFER_LENGTH + 1);
if (ctx == NULL) {
fprintf(stderr, "Error while creating decryption context.\n");
return 0;
}
if (EVP_PKEY_decrypt_init(ctx) <= 0) {
fprintf(stderr, "Error while initializing decryption context.\n");
return 0;
}
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) {
fprintf(stderr, "Error while setting decryption padding.\n");
return 0;
}
while (1) {
in_len = fread(inbuf, 1, FILE_BUFFER_LENGTH, srcfp);
if (in_len == 0) { break; }
if (EVP_PKEY_decrypt(ctx, outbuf, &out_len, inbuf, in_len) <= 0) {
fprintf(stderr, "Error while decrypting data.\n");
return 0;
}
x = fwrite(outbuf, sizeof(char), in_len, tgtfp);
if (x != in_len) {
fprintf(stderr, "Error while writing decrypted data to target file.\n");
return 0;
}
}
return 1;
}

libav: encoding/decoding error: get_buffer() failed

I am trying to edit the given Audio encoding/decoding examples of the libav located in libav-11.4/doc/examples/avcodec.c.
I simply want to encode a .wav file into aac and then decode back to .wav
But in the decoding step I allways get the following error:
[aac # 0x...] get_buffer() failed
Error while decoding
The Edited example code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_AV_CONFIG_H
#undef HAVE_AV_CONFIG_H
#endif
#include "libavcodec/avcodec.h"
#include "libavutil/channel_layout.h"
#include "libavutil/common.h"
#include "libavutil/imgutils.h"
#include "libavutil/mathematics.h"
#include "libavutil/samplefmt.h"
#define INBUF_SIZE 4096
#define AUDIO_INBUF_SIZE 20480
#define AUDIO_REFILL_THRESH 4096
/* check that a given sample format is supported by the encoder */
static int check_sample_fmt(AVCodec *codec, enum AVSampleFormat sample_fmt)
{
const enum AVSampleFormat *p = codec->sample_fmts;
while (*p != AV_SAMPLE_FMT_NONE) {
if (*p == sample_fmt)
return 1;
p++;
}
return 0;
}
/* just pick the highest supported samplerate */
static int select_sample_rate(AVCodec *codec)
{
const int *p;
int best_samplerate = 0;
if (!codec->supported_samplerates)
return 44100;
p = codec->supported_samplerates;
while (*p) {
best_samplerate = FFMAX(*p, best_samplerate);
p++;
}
return best_samplerate;
}
/* select layout with the highest channel count */
static int select_channel_layout(AVCodec *codec)
{
const uint64_t *p;
uint64_t best_ch_layout = 0;
int best_nb_channels = 0;
if (!codec->channel_layouts)
return AV_CH_LAYOUT_STEREO;
p = codec->channel_layouts;
while (*p) {
int nb_channels = av_get_channel_layout_nb_channels(*p);
if (nb_channels > best_nb_channels) {
best_ch_layout = *p;
best_nb_channels = nb_channels;
}
p++;
}
return best_ch_layout;
}
/*
* Audio encoding example
*/
static void audio_encode_example(const char *outfilename, const char *filename)
{
AVCodec *codec;
AVCodecContext *c= NULL;
AVFrame *frame;
AVPacket pkt;
int i, j, k, ret, got_output;
int buffer_size;
FILE *f, *outfile;
uint16_t *samples;
float t, tincr;
printf("Audio encoding\n");
/* find the MP2 encoder */
codec = avcodec_find_encoder(AV_CODEC_ID_AAC);
if (!codec) {
fprintf(stderr, "codec not found\n");
exit(1);
}
c = avcodec_alloc_context3(codec);
/* put sample parameters */
c->bit_rate = 64000;
/* check that the encoder supports s16 pcm input */
c->sample_fmt = AV_SAMPLE_FMT_S16;
if (!check_sample_fmt(codec, c->sample_fmt)) {
fprintf(stderr, "encoder does not support %s",
av_get_sample_fmt_name(c->sample_fmt));
exit(1);
}
/* select other audio parameters supported by the encoder */
c->sample_rate = select_sample_rate(codec);
c->channel_layout = select_channel_layout(codec);
c->channels = av_get_channel_layout_nb_channels(c->channel_layout);
/* open it */
if (avcodec_open2(c, codec, NULL) < 0) {
fprintf(stderr, "could not open codec\n");
exit(1);
}
f = fopen(filename, "rb");
if (!f) {
fprintf(stderr, "could not open %s\n", filename);
exit(1);
}
outfile = fopen(outfilename, "wb");
if (!outfile) {
fprintf(stderr, "could not open %s\n", filename);
exit(1);
}
/* frame containing input raw audio */
frame = av_frame_alloc();
if (!frame) {
fprintf(stderr, "could not allocate audio frame\n");
exit(1);
}
frame->nb_samples = c->frame_size;
frame->format = c->sample_fmt;
frame->channel_layout = c->channel_layout;
/* the codec gives us the frame size, in samples,
* we calculate the size of the samples buffer in bytes */
buffer_size = av_samples_get_buffer_size(NULL, c->channels, c->frame_size,
c->sample_fmt, 0);
samples = av_malloc(buffer_size);
if (!samples) {
fprintf(stderr, "could not allocate %d bytes for samples buffer\n",
buffer_size);
exit(1);
}
/* setup the data pointers in the AVFrame */
ret = avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt,
(const uint8_t*)samples, buffer_size, 0);
if (ret < 0) {
fprintf(stderr, "could not setup audio frame\n");
exit(1);
}
/* encode a single tone sound */
t = 0;
tincr = 2 * M_PI * 440.0 / c->sample_rate;
for(i=0;i<200;i++) {
av_init_packet(&pkt);
pkt.data = NULL; // packet data will be allocated by the encoder
pkt.size = 0;
for (j = 0; j < c->frame_size; j++) {
samples[2*j] = (int)(sin(t) * 10000);
for (k = 1; k < c->channels; k++)
samples[2*j + k] = samples[2*j];
t += tincr;
}
/* encode the samples */
ret = avcodec_encode_audio2(c, &pkt, frame, &got_output);
if (ret < 0) {
fprintf(stderr, "error encoding audio frame\n");
exit(1);
}
if (got_output) {
fwrite(pkt.data, 1, pkt.size, outfile);
av_free_packet(&pkt);
}
}
fclose(f);
fclose(outfile);
av_freep(&samples);
av_frame_free(&frame);
avcodec_close(c);
av_free(c);
}
/*
* Audio decoding.
*/
static void audio_decode_example(const char *outfilename, const char *filename)
{
AVCodec *codec;
AVCodecContext *c= NULL;
int len;
FILE *f, *outfile;
uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
AVPacket avpkt;
AVFrame *decoded_frame = NULL;
av_init_packet(&avpkt);
printf("Audio decoding\n");
/* find the mpeg audio decoder */
codec = avcodec_find_decoder(AV_CODEC_ID_AAC);
if (!codec) {
fprintf(stderr, "codec not found\n");
exit(1);
}
c = avcodec_alloc_context3(codec);
/* open it */
if (avcodec_open2(c, codec, NULL) < 0) {
fprintf(stderr, "could not open codec\n");
exit(1);
}
f = fopen(filename, "rb");
if (!f) {
fprintf(stderr, "could not open %s\n", filename);
exit(1);
}
outfile = fopen(outfilename, "wb");
if (!outfile) {
av_free(c);
exit(1);
}
/* decode until eof */
avpkt.data = inbuf;
avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f);
while (avpkt.size > 0) {
int got_frame = 0;
if (!decoded_frame) {
if (!(decoded_frame = av_frame_alloc())) {
fprintf(stderr, "out of memory\n");
exit(1);
}
}
len = avcodec_decode_audio4(c, decoded_frame, &got_frame, &avpkt);
if (len < 0) {
fprintf(stderr, "Error while decoding\n");
exit(1);
}
if (got_frame) {
/* if a frame has been decoded, output it */
int data_size = av_samples_get_buffer_size(NULL, c->channels,
decoded_frame->nb_samples,
c->sample_fmt, 1);
fwrite(decoded_frame->data[0], 1, data_size, outfile);
}
avpkt.size -= len;
avpkt.data += len;
if (avpkt.size < AUDIO_REFILL_THRESH) {
/* Refill the input buffer, to avoid trying to decode
* incomplete frames. Instead of this, one could also use
* a parser, or use a proper container format through
* libavformat. */
memmove(inbuf, avpkt.data, avpkt.size);
avpkt.data = inbuf;
len = fread(avpkt.data + avpkt.size, 1,
AUDIO_INBUF_SIZE - avpkt.size, f);
if (len > 0)
avpkt.size += len;
}
}
fclose(outfile);
fclose(f);
avcodec_close(c);
av_free(c);
av_frame_free(&decoded_frame);
}
int main(int argc, char **argv)
{
const char *filename;
/* register all the codecs */
avcodec_register_all();
filename = argv[1];
audio_encode_example("test.aac", filename);
audio_decode_example("out.wav", "test.aac");
return 0;
}
EDIT:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_AV_CONFIG_H
#undef HAVE_AV_CONFIG_H
#endif
#include "libavcodec/avcodec.h"
#include "libavutil/channel_layout.h"
#include "libavutil/common.h"
#include "libavutil/imgutils.h"
#include "libavutil/mathematics.h"
#include "libavutil/samplefmt.h"
#include "libavformat/avformat.h"
#define INBUF_SIZE 4096
#define AUDIO_INBUF_SIZE 20480
#define AUDIO_REFILL_THRESH 4096
/* check that a given sample format is supported by the encoder */
static int check_sample_fmt(AVCodec *codec, enum AVSampleFormat sample_fmt)
{
const enum AVSampleFormat *p = codec->sample_fmts;
while (*p != AV_SAMPLE_FMT_NONE) {
if (*p == sample_fmt)
return 1;
p++;
}
return 0;
}
/* just pick the highest supported samplerate */
static int select_sample_rate(AVCodec *codec)
{
const int *p;
int best_samplerate = 0;
if (!codec->supported_samplerates)
return 44100;
p = codec->supported_samplerates;
while (*p) {
best_samplerate = FFMAX(*p, best_samplerate);
p++;
}
return best_samplerate;
}
/* select layout with the highest channel count */
static int select_channel_layout(AVCodec *codec)
{
const uint64_t *p;
uint64_t best_ch_layout = 0;
int best_nb_channels = 0;
if (!codec->channel_layouts)
return AV_CH_LAYOUT_STEREO;
p = codec->channel_layouts;
while (*p) {
int nb_channels = av_get_channel_layout_nb_channels(*p);
if (nb_channels > best_nb_channels) {
best_ch_layout = *p;
best_nb_channels = nb_channels;
}
p++;
}
return best_ch_layout;
}
/*
* Audio encoding example
*/
static void audio_encode_example(const char *outfilename, const char *filename)
{
AVCodec *codec;
AVCodecContext *c= NULL;
AVFrame *frame;
AVPacket pkt;
int i, j, k, ret, got_output;
int buffer_size;
FILE *f, *outfile;
uint16_t *samples;
float t, tincr;
printf("Audio encoding\n");
/* find the MP2 encoder */
codec = avcodec_find_encoder(AV_CODEC_ID_AAC);
if (!codec) {
fprintf(stderr, "codec not found\n");
exit(1);
}
c = avcodec_alloc_context3(codec);
/* put sample parameters */
c->bit_rate = 64000;
/* check that the encoder supports s16 pcm input */
c->sample_fmt = AV_SAMPLE_FMT_S16;
if (!check_sample_fmt(codec, c->sample_fmt)) {
fprintf(stderr, "encoder does not support %s",
av_get_sample_fmt_name(c->sample_fmt));
exit(1);
}
/* select other audio parameters supported by the encoder */
c->sample_rate = select_sample_rate(codec);
c->channel_layout = select_channel_layout(codec);
c->channels = av_get_channel_layout_nb_channels(c->channel_layout);
/* open it */
if (avcodec_open2(c, codec, NULL) < 0) {
fprintf(stderr, "could not open codec\n");
exit(1);
}
f = fopen(filename, "rb");
if (!f) {
fprintf(stderr, "could not open %s\n", filename);
exit(1);
}
outfile = fopen(outfilename, "wb");
if (!outfile) {
fprintf(stderr, "could not open %s\n", filename);
exit(1);
}
/* frame containing input raw audio */
frame = av_frame_alloc();
if (!frame) {
fprintf(stderr, "could not allocate audio frame\n");
exit(1);
}
frame->nb_samples = c->frame_size;
frame->format = c->sample_fmt;
frame->channel_layout = c->channel_layout;
/* the codec gives us the frame size, in samples,
* we calculate the size of the samples buffer in bytes */
buffer_size = av_samples_get_buffer_size(NULL, c->channels, c->frame_size,
c->sample_fmt, 0);
samples = av_malloc(buffer_size);
if (!samples) {
fprintf(stderr, "could not allocate %d bytes for samples buffer\n",
buffer_size);
exit(1);
}
/* setup the data pointers in the AVFrame */
ret = avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt,
(const uint8_t*)samples, buffer_size, 0);
if (ret < 0) {
fprintf(stderr, "could not setup audio frame\n");
exit(1);
}
/* encode a single tone sound */
t = 0;
tincr = 2 * M_PI * 440.0 / c->sample_rate;
for(i=0;i<200;i++) {
av_init_packet(&pkt);
pkt.data = NULL; // packet data will be allocated by the encoder
pkt.size = 0;
for (j = 0; j < c->frame_size; j++) {
samples[2*j] = (int)(sin(t) * 10000);
for (k = 1; k < c->channels; k++)
samples[2*j + k] = samples[2*j];
t += tincr;
}
/* encode the samples */
ret = avcodec_encode_audio2(c, &pkt, frame, &got_output);
if (ret < 0) {
fprintf(stderr, "error encoding audio frame\n");
exit(1);
}
if (got_output) {
fwrite(pkt.data, 1, pkt.size, outfile);
av_free_packet(&pkt);
}
}
fclose(f);
fclose(outfile);
av_freep(&samples);
av_frame_free(&frame);
avcodec_close(c);
av_free(c);
}
/*
* Audio decoding.
*/
static void audio_decode_example(const char *outfilename, const char *filename)
{
AVCodec *codec;
AVCodecContext *c= NULL;
int len;
FILE *f, *outfile;
uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
AVPacket avpkt;
AVFrame *decoded_frame = NULL;
av_init_packet(&avpkt);
printf("Audio decoding\n");
/* find the mpeg audio decoder */
codec = avcodec_find_decoder(AV_CODEC_ID_AAC);
if (!codec) {
fprintf(stderr, "codec not found\n");
exit(1);
}
c = avcodec_alloc_context3(codec);
/* open it */
if (avcodec_open2(c, codec, NULL) < 0) {
fprintf(stderr, "could not open codec\n");
exit(1);
}
/*
f = fopen(filename, "rb");
if (!f) {
fprintf(stderr, "could not open %s\n", filename);
exit(1);
}
*/
AVFormatContext *s = avformat_alloc_context();
int ret = avformat_open_input(&s, filename, NULL, NULL);
if (ret != 0)
{
abort();
}
// Retrieve stream information
printf("sdfsdf\n");
if(avformat_find_stream_info(s, NULL)<0)
{
printf("Could not find stream info");// Couldn't find stream information
}
// Dump information about file into standard error
av_dump_format(s, 0, filename, 0);
outfile = fopen(outfilename, "wb");
if (!outfile) {
av_free(c);
exit(1);
}
/* decode until eof */
//avpkt.data = inbuf;
//avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f);
int read_ok = av_read_frame(s,&avpkt);
while (read_ok)
{
read_ok = av_read_frame(s,&avpkt);
int got_frame = 0;
if (!decoded_frame) {
if (!(decoded_frame = av_frame_alloc())) {
fprintf(stderr, "out of memory\n");
exit(1);
}
}
len = avcodec_decode_audio4(c, decoded_frame, &got_frame, &avpkt);
if (len < 0) {
fprintf(stderr, "Error while decoding\n");
exit(1);
}
if (got_frame) {
/* if a frame has been decoded, output it */
int data_size = av_samples_get_buffer_size(NULL, c->channels,
decoded_frame->nb_samples,
c->sample_fmt, 1);
fwrite(decoded_frame->data[0], 1, data_size, outfile);
}
/*
avpkt.size -= len;
avpkt.data += len;
if (avpkt.size < AUDIO_REFILL_THRESH) {
memmove(inbuf, avpkt.data, avpkt.size);
avpkt.data = inbuf;
len = fread(avpkt.data + avpkt.size, 1,
AUDIO_INBUF_SIZE - avpkt.size, f);
if (len > 0)
avpkt.size += len;
}*/
}
fclose(outfile);
// fclose(f);
avcodec_close(c);
av_free(c);
av_frame_free(&decoded_frame);
}
int main(int argc, char **argv)
{
const char *filename;
/* register all the codecs */
avcodec_register_all();
av_register_all();
filename = argv[1];
audio_encode_example("test.aac", filename);
audio_decode_example("out.wav", "test.aac");
return 0;
}
See this post, you can't use fopen/fread to feed raw AAC data into the decoder, you need to use av_read_frame().

PEM_read_RSA_PUBKEY error "Expecting: PUBLIC KEY"

I am trying to implement OpenSSL RSA, following is my code for Key generation :
#include <stdio.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/bio.h>
#include <openssl/pem.h>
#define SECFILE "sec.pem"
#define PUBFILE "pub.pem"
int main()
{
EVP_PKEY_CTX *ctx;
EVP_PKEY *pkey = NULL;
ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
BIO *bio_out = NULL;
FILE *fp;
if (!ctx)
{
perror("Error in CTX \n");
}
if (EVP_PKEY_keygen_init(ctx) <= 0)
{
perror("Error in EVP_PKEY_keygen_init \n");
}
if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048) <= 0)
{
perror("Error in EVP_PKEY_CTX_set_rsa_keygen_bits \n");
}
/* Generate key */
if (EVP_PKEY_keygen(ctx, &pkey) <= 0)
{
/* Error */
perror("Error in EVP_PKEY_keygen \n");
}
fp = fopen(SECFILE, "w");
if ((bio_out = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL)
{
perror("Error in new BIO \n");
}
BIO_set_flags(bio_out, BIO_FLAGS_WRITE);
EVP_PKEY_print_private(bio_out,pkey,5, NULL);
fclose(fp);
BIO_free(bio_out);
fp = fopen(PUBFILE, "w");
if ((bio_out = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL)
{
perror("Error in new BIO \n");
}
BIO_set_flags(bio_out, BIO_FLAGS_WRITE);
EVP_PKEY_print_public(bio_out,pkey,5, NULL);
fclose(fp);
BIO_free(bio_out);
return 0;
}
And here is the pub.pem:
Public-Key: (2048 bit)
Modulus:
00:be:bc:04:74:39:5b:31:2d:76:bf:41:9a:3e:6e:
d0:cf:8f:c3:25:86:6b:38:ff:58:96:fc:bb:2b:d9:
af:df:fa:bf:aa:1e:c7:58:1d:2b:ce:6c:90:0f:d3:
30:b7:90:fc:1c:7c:84:f3:31:80:3e:04:ad:bd:74:
dc:92:60:01:9e:40:82:31:b3:8d:a5:ac:fb:81:83:
c5:e9:e6:56:0b:f4:df:dd:f3:e4:7f:3b:b6:85:d7:
c9:41:08:3f:bf:15:bd:6d:19:ff:13:fc:4a:52:59:
93:77:b0:be:78:01:da:db:b2:7d:f9:38:98:e0:d2:
45:79:3c:60:0d:a1:65:74:d2:9c:9b:7c:15:2c:e4:
ee:eb:76:52:f3:61:95:8b:d6:fb:5e:fb:f7:c6:40:
70:77:86:fb:60:87:07:f3:58:49:74:d6:0a:cf:d4:
70:09:50:73:20:1e:4e:52:4c:59:34:a0:f5:7a:80:
57:e5:8a:8c:d1:a1:94:a4:ab:75:99:fd:55:62:06:
34:dd:83:00:aa:3f:c8:0a:a1:0e:80:1a:ba:42:6e:
23:37:eb:bd:1f:e4:a2:c4:fa:2a:84:84:e4:dc:ec:
a2:a5:36:2c:c6:cb:28:81:8c:89:15:64:f4:ef:ec:
1e:c8:c3:d5:c2:02:54:ce:bb:72:20:b4:4a:05:2f:
dc:75
Exponent: 65537 (0x10001)
Following is the code which I am using for encryption:
#include <stdio.h>
#include <stdlib.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/err.h>
#include <arpa/inet.h> /* For htonl() */
int do_evp_seal(FILE *rsa_pkey_file, FILE *in_file, FILE *out_file)
{
int retval = 0;
RSA *rsa_pkey = NULL;
EVP_PKEY *pkey = EVP_PKEY_new();
EVP_CIPHER_CTX ctx;
unsigned char buffer[4096];
unsigned char buffer_out[4096 + EVP_MAX_IV_LENGTH];
size_t len;
int len_out;
unsigned char *ek;
int eklen;
uint32_t eklen_n;
unsigned char iv[EVP_MAX_IV_LENGTH];
if (!PEM_read_RSA_PUBKEY(rsa_pkey_file, &rsa_pkey, NULL, NULL))
{
fprintf(stderr, "Error loading RSA Public Key File.\n");
// here I am getting this error:
// 140121481717416:error:0906D06C:lib(9):func(109):reason(108):pem_lib.c:696:Expecting: PUBLIC KEY
ERR_print_errors_fp(stderr);
retval = 2;
goto out;
}
EVP_CIPHER_CTX_init(&ctx);
ek = malloc(EVP_PKEY_size(pkey));
if (!EVP_SealInit(&ctx, EVP_aes_128_cbc(), &ek, &eklen, iv, &pkey, 1))
{
fprintf(stderr, "EVP_SealInit: failed.\n");
retval = 3;
goto out_free;
}
/* First we write out the encrypted key length, then the encrypted key,
* then the iv (the IV length is fixed by the cipher we have chosen).
*/
eklen_n = htonl(eklen);
if (fwrite(&eklen_n, sizeof eklen_n, 1, out_file) != 1)
{
perror("output file");
retval = 5;
goto out_free;
}
if (fwrite(ek, eklen, 1, out_file) != 1)
{
perror("output file");
retval = 5;
goto out_free;
}
if (fwrite(iv, EVP_CIPHER_iv_length(EVP_aes_128_cbc()), 1, out_file) != 1)
{
perror("output file");
retval = 5;
goto out_free;
}
/* Now we process the input file and write the encrypted data to the
* output file. */
while ((len = fread(buffer, 1, sizeof buffer, in_file)) > 0)
{
if (!EVP_SealUpdate(&ctx, buffer_out, &len_out, buffer, len))
{
fprintf(stderr, "EVP_SealUpdate: failed.\n");
retval = 3;
goto out_free;
}
if (fwrite(buffer_out, len_out, 1, out_file) != 1)
{
perror("output file");
retval = 5;
goto out_free;
}
}
if (ferror(in_file))
{
perror("input file");
retval = 4;
goto out_free;
}
if (!EVP_SealFinal(&ctx, buffer_out, &len_out))
{
fprintf(stderr, "EVP_SealFinal: failed.\n");
retval = 3;
goto out_free;
}
if (fwrite(buffer_out, len_out, 1, out_file) != 1)
{
perror("output file");
retval = 5;
goto out_free;
}
out_free:
EVP_PKEY_free(pkey);
free(ek);
out:
return retval;
}
int main(int argc, char *argv[])
{
FILE *rsa_pkey_file;
int rv;
rsa_pkey_file = fopen("pub.pem", "rb");
if (!rsa_pkey_file)
{
fprintf(stderr, "Error loading PEM RSA Public Key File.\n");
exit(2);
}
rv = do_evp_seal(rsa_pkey_file, stdin, stdout);
fclose(rsa_pkey_file);
return rv;
}
Why is PEM_read_RSA_PUBKEY returning ERROR: Expecting PUBLIC KEY?
OK, I found out myself I have write PEM_write_bio_PUBKEY(bio_out,pkey ); instead of EVP_PKEY_print_public(bio_out,pkey)

Getting error in EVP_OpenInit() of OpenSSL EVP api for RSA decryption, in C

I am facing a problem in RSA decryption using OpenSSL Library (EVP api).
Here is my code for key generation
#include <stdio.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/bio.h>
#include <openssl/pem.h>
#define SECFILE "sec.pem"
#define PUBFILE "pub.pem"
int main()
{
EVP_PKEY_CTX *ctx;
EVP_PKEY *pkey = NULL;
ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
FILE *fp;
if (!ctx)
{
/* Error occurred */
perror("Error in CTX \n");
}
if (EVP_PKEY_keygen_init(ctx) <= 0)
{
/* Error */
perror("Error in EVP_PKEY_keygen_init \n");
}
if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048) <= 0)
{
/* Error */
perror("Error in EVP_PKEY_CTX_set_rsa_keygen_bits \n");
}
/* Generate key */
if (EVP_PKEY_keygen(ctx, &pkey) <= 0)
{
/* Error */
perror("Error in EVP_PKEY_keygen \n");
}
fp = fopen(SECFILE, "w");
PEM_write_PrivateKey(fp, pkey, NULL,NULL, 0,0, NULL);
fclose(fp);
fp = fopen(PUBFILE, "w");
PEM_write_PUBKEY(fp,pkey);
fclose(fp);
return 0;
}
For encryption :
I used this link
For decryption :
int do_evp_open(FILE *rsa_pkey_file, FILE *in_file, FILE *out_file)
{
int retval = 0;
RSA *rsa_pkey = NULL;
EVP_PKEY *pkey = EVP_PKEY_new();
EVP_CIPHER_CTX ctx;
unsigned char buffer[4096];
unsigned char buffer_out[4096 + EVP_MAX_IV_LENGTH];
size_t len;
int len_out;
unsigned char *ek;
int eklen ;
uint32_t eklen_n;
unsigned char iv[EVP_MAX_IV_LENGTH] = {122,205,106,192,4,183,69,176,84,28,214,226,220,140,86,174};
/// Read RSA Private Key
if (PEM_read_RSAPrivateKey(rsa_pkey_file, &rsa_pkey, NULL, NULL) == NULL)
{
fprintf(stderr, "Error loading RSA Private Key File.\n");
ERR_print_errors_fp(stderr);
retval = -2;
goto out;
}
/// Assign RSA key to EVP key
if (!EVP_PKEY_assign_RSA(pkey, rsa_pkey))
{
fprintf(stderr, "EVP_PKEY_assign_RSA: failed.\n");
retval = -3;
goto out;
}
EVP_CIPHER_CTX_init(&ctx);
ek = malloc( EVP_PKEY_size(pkey));
if (!EVP_OpenInit(&ctx, EVP_aes_128_cbc(), ek, eklen, iv,pkey))
{
fprintf(stderr, "EVP_OpenInit: failed.\n");
ERR_print_errors_fp(stderr); /// Prints error of occured in Openssl
retval = -3;
goto out_free;
}
while ((len = fread(buffer, 1, sizeof buffer, in_file)) > 0)
{
if (!EVP_OpenUpdate(&ctx, buffer_out, &len_out, buffer, len))
{
fprintf(stderr, "EVP_OpenUpdate: failed.\n");
retval = 3;
goto out_free;
}
if (fwrite(buffer_out, len_out, 1, out_file) != 1)
{
perror("output file");
retval = -5;
goto out_free;
}
}
if (ferror(in_file))
{
perror("input file");
retval = -4;
goto out_free;
}
if (!EVP_OpenFinal(&ctx, buffer_out, &len_out))
{
fprintf(stderr, "EVP_OpenFinal: failed.\n");
retval = - 3;
goto out_free;
}
if (fwrite(buffer_out, len_out, 1, out_file) != 1)
{
perror("output file");
retval = -5;
goto out_free;
}
out_free:
EVP_PKEY_free(pkey);
free(ek);
out:
return retval;
}
My Private and public keys are :
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDj+g6m7KY5zK8z
FZ/MKFySr1ZB+n0b3GjhMUcUDn5S9N7oyoCzkOVVa7gl0jTI8dwCFVAy8693Rq+i
AT7dUTLViT9V8GkX9r0yFcppt5uc2YgI5aOOTvmQKQe08FSZ7QbviEL25MNnBfB1
wpd+mJN3nb0hkeo7x2IZD/ZVfs+TmOG9mHbQR8b1XcxEDoLx3aX1J8Eix1pN7YK6
nDAFm984Ho+PCz1aGl/TnDl3b90X5HXGHiD6uNDHokZ+th8B6AeFFRlkWlQd0w2R
e/EEZ36p4TQOHSc3sSUw6pen0N8YmBNZksBEr1vsZvYkKtRKCfy0fXtL4iqKzcgJ
ocos+Z6nAgMBAAECggEBALlWDdlYpF5y76/JEaso2PGLR8XFvTYMPttsc0tz6PDK
D/oSvwS8dCS4uPFObgk6ztCGwTda8rg2KAy9lHzaSUheFrZoBxgrSG5SVscRNJoU
IsqQ3iGQRMUVBiXsB+tHTg8nqMENA2pa4rzpoL2Tjrd87kg/VryYgEC9wFaLDHgB
FaXJJlaeuTBQXV7Ga9pg+KF1Kv91/q3T62Um0ggSajFpX15x6sLIo5EWm0DGksn0
chQeiEs33e8fHil95g0nXK+hXOMnMvbAln/eOCGktO4JnPTjicAA7iKliCsLiaeZ
t5Czscv/8AVlBAISGJcE8ASM+AbalXtnoOK6W+dv0gkCgYEA/cPi7U8bJ0tlvxF3
3vc8V7uzuAgKtOKQet1spQtAoi343ZoSyFHQEwO5PMmtB56/mk3+/mDpoKTQo0oK
f5COIlzW+PIMQCroalpJe+ZcY/PS8SPoOY39yiX4WQchgac01R0Qf6XDAOfyfZ9d
MZTtDgpkx/oyfRTzxI7D9SZUqZ0CgYEA5fwH5uwmc0fsIw3tl3pHHOK9g78Rs6XE
0feXplBCzx+qaEtAK1Jp1nMX/PmN575i3UN3dii9YV8v9geTf+hytpQd/TbrvsSY
Py9j95XYN75Z5TAsWnZbZr/gTdZSz0yObb/9GzxBipp+EHCEOSS0RF8u9XHlM9bC
0agB4VZKqBMCgYByIjxaR44K6lpkyVKEseYt/3ohd1x5Zr1cxWIsCReU2eBoqvdv
qXxQUQhrUrnEB55dpF7fwm7Rlc9Q4eg+36FNyzvU0+i2o5XM37bVRxKe0fc6BdBY
sohG9zTvtclYKwAUKfJVtxQxwCDMZ3Te7ACCpCIX32v93gKVkTCJfift8QKBgHZ9
PAEAZ+r7AjEpSuDBMgQy2ZsYBOG+pUHcQzh/n3wg/2XOZ1gqlLbVA2XlmPPtxffj
e5fX84JITWh/jMHYm8lvVGgSNLFLjnj3TJTRkd1eZ+hJwoA0/HBaqRDRPEbrVXI7
+QZgLBBh+lMz9RuPyoRzWblBHepwWl00JwvWro4bAoGBAKFAXVzbx74JM6wzr9H5
TusTwOM5mf/I1TkCq1Dd5n1vDVfrkNokZ2LfJWqiQHLZj2rGxSQSVjIsVaBmEDTZ
ob8duUsbkYQe4dToHFHcBO+akBtULC4HWv/D4pPVoyAE7WJBJBw0vl1sA15kiXBu
HBXffOzN/Erqvp90HLtefpMp
-----END PRIVATE KEY-----
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4/oOpuymOcyvMxWfzChc
kq9WQfp9G9xo4TFHFA5+UvTe6MqAs5DlVWu4JdI0yPHcAhVQMvOvd0avogE+3VEy
1Yk/VfBpF/a9MhXKabebnNmICOWjjk75kCkHtPBUme0G74hC9uTDZwXwdcKXfpiT
d529IZHqO8diGQ/2VX7Pk5jhvZh20EfG9V3MRA6C8d2l9SfBIsdaTe2CupwwBZvf
OB6Pjws9Whpf05w5d2/dF+R1xh4g+rjQx6JGfrYfAegHhRUZZFpUHdMNkXvxBGd+
qeE0Dh0nN7ElMOqXp9DfGJgTWZLARK9b7Gb2JCrUSgn8tH17S+Iqis3ICaHKLPme
pwIDAQAB
-----END PUBLIC KEY-----
The error I am getting While EVP_OpenInit is :
140004942804648:error:0407106B:lib(4):func(113):reason(107):rsa_pk1.c:190: 140004942804648:error:04065072:lib(4):func(101):reason(114):rsa_eay.c:594
Any help would be appreciated.
Thanks,
Pawan
Are you absolutely sure, that you have initialized variable eklen?
I see you have used EVP_OpenInit(), EVP_OpenUpdate() and EVP_OpenFinal() for decryption. So I'm going to assume that you've used EVP_SealInit(), EVP_SealUpdate() and EVP_SealFinal() functions for encryption.
So if you have used EVP_SealInit(), you must have passed the address (pointer) to eklen (please check man EVP_SealInit) where the variable gets a value assigned. In analogous to that the eklen variable that you are passing to EVP_OpenInit() must contain a valid key length.
The following is the description from man EVP_OpenInit.
EVP_OpenInit() initializes a cipher context ctx for decryption with cipher type. It decrypts the encrypted symmetric key of length ekl bytes passed in the ek parameter using the private key priv. The IV is supplied in the iv parameter.
I'm not sure here, but I guess you need to use EVP_PKEY_size() function in this case to get the length of the key.
For example (in your decryption code):
....
..
.
EVP_CIPHER_CTX_init(&ctx);
ek = malloc( EVP_PKEY_size(pkey));
/* Add the following line */
eklen = EVP_PKEY_size(pkey);
if (!EVP_OpenInit(&ctx, EVP_aes_128_cbc(), ek, eklen, iv,pkey))
{
fprintf(stderr, "EVP_OpenInit: failed.\n");
...
..
.

Resources