I'm trying to develop an RSA engine. My engine was somewhat working until I try to integrate my engine with an apache httpd server. After installing the httpd from the source code, it turns out that, I can't compile my engine code anymore. I get the following error while I try to compile (it was compiling before and I did not make any changes to my engine code).
$gcc -fPIC -c r_engine.c
r_engine.c:29:8: error: redefinition of ‘struct rsa_meth_st’
struct rsa_meth_st {
^
In file included from /usr/include/openssl/crypto.h:131:0,
from r_engine.c:7:
/usr/include/openssl/ossl_typ.h:147:16: note: originally defined here
typedef struct rsa_meth_st RSA_METHOD;
My sample source code is like the following,
#include <openssl/opensslconf.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <openssl/crypto.h>
#include <openssl/buffer.h>
#include <openssl/engine.h>
#include <openssl/rsa.h>
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/ossl_typ.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
/* Declared in ossl_typ.h */
/* typedef struct rsa_meth_st RSA_METHOD; */
//#ifndef INCLUDE_OSSL_TYP_H
//#define INCLUDE_OSSL_TYP_H
struct rsa_meth_st {
const char *name;
int (*rsa_pub_enc) (int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding);
int (*rsa_pub_dec) (int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding);
int (*rsa_priv_enc) (int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding);
int (*rsa_priv_dec) (int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding);
int (*rsa_mod_exp) (BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);
int (*bn_mod_exp) (BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
int (*init) (RSA *rsa);
int (*finish) (RSA *rsa);
int flags;
char *app_data;
int (*rsa_sign) (int type, const unsigned char *m, unsigned int m_length, unsigned char *sigret, unsigned int *siglen, const RSA *rsa);
int (*rsa_verify) (int dtype, const unsigned char *m, unsigned int m_length, const unsigned char *sigbuf, unsigned int siglen, const RSA *rsa);
int (*rsa_keygen) (RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
};
//#endif
static int eng_rsa_pub_enc (int flen, const unsigned char *from, unsigned char *to, RSA * rsa, int padding){
printf ("Engine is encrypting using pub key \n");
}
static int eng_rsa_pub_dec (int flen, const unsigned char *from, unsigned char *to, RSA * rsa, int padding){
printf ("Engine is decrypting using pub key \n");
}
static int eng_rsa_priv_enc (int flen, const unsigned char *from, unsigned char *to, RSA * rsa, int padding __attribute__ ((unused))){
printf ("Engine is encrypting using priv key \n");
}
static int eng_rsa_priv_dec (int flen, unsigned char *from, unsigned char *to, RSA * rsa, int padding __attribute__ ((unused))){
printf ("Engine is decrypting using priv key \n");
}
/* Constants used when creating the ENGINE */
static const char *engine_rsa_id = "r_engine";
static const char *engine_rsa_name = "Demo engine";
struct rsa_meth_st new_rsa =
{
"demo RSA Engine",
eng_rsa_pub_enc,
eng_rsa_pub_dec,
eng_rsa_priv_enc,
eng_rsa_priv_dec,
NULL,
NULL,
NULL,
NULL,
RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE,
NULL,
NULL,
NULL,
NULL
};
static int bind (ENGINE * e, const char *id){
printf ("%s\n", id);
if (!ENGINE_set_id (e, engine_rsa_id) ||
!ENGINE_set_name (e, engine_rsa_name) ||
!ENGINE_set_RSA (e, &new_rsa))
return 0;
return 1;
}
IMPLEMENT_DYNAMIC_BIND_FN (bind)
IMPLEMENT_DYNAMIC_CHECK_FN ()
I notice that, with a fresh version of OS, my code compiles and runs well.
I understand that struct rsa_meth_st was defined in ossl_typ.h file, but that did not throw any error previously but why now?
My gcc version is gcc (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609
This seems like a case where you have been building with two different branches of OpenSSL. Between the 1.0.2 and the 1.1.1 branches, quite a few types were made opaque. This means that certain structure definitions that were publicly visible in 1.0.2 are private in 1.1.1. Your struct rsa_meth_st is one of them. Therefore your code compiles with 1.1.1 but not with 1.0.2.
The solution to your problem depends on which OpenSSL version you want to use. In either case, you have to remove the entire struct rsa_meth_st definition from your code. If you intend to build with 1.0.2 (which is now out of support), then its definition is known already and exposed via the header files so you don't need to repeat it yourself. If you intend to build with 1.1.1, you have to use RSA_meth_new() followed by the appropriate RSA_meth_set_() functions.
In general, when you see constructs like typedef struct rsa_meth_st RSA_METHOD you are typically not supposed to define that same struct yourself because it is already defined somewhere else (visibly or hidden). Instead, you should refer to that type via RSA_METHOD or, more likely, RSA_METHOD *.
Related
I was unable to understand what do these 2 round parenthesis mean ?
struct conf_method_st {
const char *name;
CONF *(*create) (CONF_METHOD *meth);
int (*init) (CONF *conf);
int (*destroy) (CONF *conf);
int (*destroy_data) (CONF *conf);
int (*load_bio) (CONF *conf, BIO *bp, long *eline);
int (*dump) (const CONF *conf, BIO *bp);
int (*is_number) (const CONF *conf, char c);
int (*to_int) (const CONF *conf, char c);
int (*load) (CONF *conf, const char *name, long *eline);
};
I am guessing some sort of type-cast or initialization is going on. Can anyone explain ?
This is the syntax for a function pointer type.
Taking the first example:
CONF *(*create) (CONF_METHOD *meth);
It defines a struct member named create which points to a function receiving a single parameter of type CONF_METHOD* and returning a value of type CONF*
So, for example, if you had a function:
CONF *my_create(CONF_METHOD* meth)
{
//...
}
Then you could store a pointer to that function in your struct:
struct conf_method_st c;
c.create = my_create;
And you can invoke it just like a function:
CONF *conf = c.create(meth);
I am trying to convert this example (found here) from the openssl documentation to work with LuaJIT's FFI. Scroll down for complete Lua code.
BIO *bio, *b64;
char message[] = "Hello World \n";
b64 = BIO_new(BIO_f_base64());
bio = BIO_new_fp(stdout, BIO_NOCLOSE);
BIO_push(b64, bio);
BIO_write(b64, message, strlen(message));
BIO_flush(b64);
BIO_free_all(b64);
But when I get to this line in the code ssl.BIO_flush(b64)I am getting the error below (running this from the LuaJIT interpreter and not a file)
stdin:1: Symbol not found: BIO_flush
stack traceback:
[C]: in function '__index'
stdin:1: in main chunk
[C]: at 0x0ac2cdd2f176
I understand that there are many other ways to do base64 encoding and at this point I have switched to a pure Lua solution. I still would like to understand why I'm getting this error because in part I'm working on this project to learn more about the LuaJIT FFI interface and openssl is already a dependency for libcurl which I am already using (hitting various APIs with OAth and I want to keep my dependencies as lean as possible).
I have already been successful at using openssl's HMAC() authentication function (found here) from LuaJIT's FFI so through reading documentation and trial and error I am pretty familiar with LuaJIT's FFI interface. Lua code below. I had to navigate through MANY openssl header files to get to this ffi.cdef[[]] but seems like maybe I'm still missing something. Any help would be appreciated.
EDIT: Just to test if the BIO_flush() is somehow optional, I've also excluded that line and gone all the way through my code with no errors but then I check the output file and it is blank.
ffi = require "ffi"
ffi.cdef[[
typedef struct bio_method_st BIO_METHOD;
typedef struct bio_st BIO;
typedef void bio_info_cb(BIO *, int, const char *, int, long, long);
struct crypto_ex_data_st { struct stack_st_void *sk; };
typedef struct crypto_ex_data_st CRYPTO_EX_DATA;
typedef void CRYPTO_RWLOCK;
typedef long (*BIO_callback_fn)(BIO *b, int oper, const char *argp, int argi,long argl, long ret);
typedef long (*BIO_callback_fn_ex)(BIO *b, int oper, const char *argp,size_t len, int argi,long argl, int ret, size_t *processed);
struct bio_st { const BIO_METHOD *method; BIO_callback_fn callback; BIO_callback_fn_ex callback_ex; char *cb_arg;int init; int shutdown; int flags;int retry_reason; int num; void *ptr; struct bio_st *next_bio;struct bio_st *prev_bio;int references; uint64_t num_read; uint64_t num_write; CRYPTO_EX_DATA ex_data; CRYPTO_RWLOCK *lock; };
struct bio_method_st { int type; const char *name; int (*bwrite) (BIO *, const char *, size_t, size_t *); int (*bwrite_old) (BIO *, const char *, int); int (*bread) (BIO *, char *, size_t, size_t *); int (*bread_old) (BIO *, char *, int); int (*bputs) (BIO *, const char *); int (*bgets) (BIO *, char *, int); long (*ctrl) (BIO *, int, long, void *); int (*create) (BIO *); int (*destroy) (BIO *); long (*callback_ctrl) (BIO *, int, bio_info_cb *); };
typedef struct { char *fpos; void *base; unsigned short handle; short flags; short unget; unsigned long alloc; unsigned short buffincrement; } FILE;
BIO *BIO_new(BIO_METHOD *type);
BIO *BIO_new_fp(FILE *stream, int close_flag);
BIO *BIO_push(BIO *b, BIO *append);
int BIO_write(BIO *b, const void *data, int dlen);
int BIO_read(BIO *b, void *buf, int len);
int BIO_flush(BIO *b);
void BIO_free_all(BIO *a);
BIO_METHOD *BIO_f_base64(void);
FILE *fopen(const char *filename, const char *mode);
int fprintf(FILE *stream, const char *format, ...);
int fclose(FILE *stream);
]]
BIO_NOCLOSE = 0 --# define BIO_NOCLOSE 0x00
BIO_CLOSE = 1 --# define BIO_CLOSE 0x01
ssl = ffi.load('/usr/lib/libssl.so')
f = ffi.C.fopen("/tmp/test", "a+")
bio = ffi.new('BIO')
b64 = ffi.new('BIO')
str = "Hello World"
b64 = ssl.BIO_new(ssl.BIO_f_base64())
bio = ssl.BIO_new_fp(f, BIO_NOCLOSE)
ssl.BIO_push(b64, bio)
=ssl.BIO_write(b64, str, #str) --This yields 11 in the Lua interpreter. This function returns an int with the number of bytes successfully written so apparently the string was written to the file.
ssl.BIO_flush(b64)
ssl.BIO_free_all(b64)
ffi.C.fclose(f)
Protocol.h
typedef struct sDevice_d
{
char name[24];
signed int (*Send)(unsigned char*, unsigned short);
signed int (*Recv)(unsigned char*, unsigned short);
} sDevice_d, *psDevice_d;
Device.c
#include "Protocol.h"
sDevice_d sDevice = { "ten", I2c_Send };
psDevice_d psDevice = &sDevice;
static signed int I2c_Send(unsigned char* buf, unsigned short len)
{
return 0;
}
In the code above I am getting the following Error:
error C2099: initializer is not a constant
Please help me in resolving this.
I am using Visual studio Win32 application.
The function I2c_Send needs to be defined and visible
before attempting to create and initializing a struct using
it in its initializer list. I have included an adaptation of your code
below that illustrates this in two files:
protocol.h
typedef struct
{
char name[24];
signed int (*Send)(unsigned char*, unsigned short);
signed int (*Recv)(unsigned char*, unsigned short);
} S_DEVICE;
//prototype here
static signed int I2c_Send(unsigned char* buf, unsigned short len);
device.c
#include "protcol.h"
S_DEVICE sDevice_d = {"ten", I2c_Send, I2c_Send};
int main(void)
{
return 0;
}
//define here
static signed int I2c_Send(unsigned char* buf, unsigned short len)
{
return 0;
}
This source compiled and built using an ANCI C compiler (using C99 extensions) and should yield
similar results in your Visual Studios, Win32 environment.
error when compiling kernel, this really gives me headache. couldnt figure out whats wrong. multi-line macro definition already escaped by newline.
actual error is
include/linux/mmc/sdio_func.h:169:2: error: expected identifier or '(' before ')' token
header file that trigger the error
/*
* include/linux/mmc/sdio_func.h
*
* Copyright 2007-2008 Pierre Ossman
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*/
#ifndef MMC_SDIO_FUNC_H
#define MMC_SDIO_FUNC_H
#include <linux/device.h>
#include <linux/mod_devicetable.h>
#include <linux/mmc/pm.h>
struct mmc_card;
struct sdio_func;
typedef void (sdio_irq_handler_t)(struct sdio_func *);
/*
* Structure used to hold embedded SDIO device data from platform layer
*/
struct sdio_embedded_func {
uint8_t f_class;
uint32_t f_maxblksize;
};
/*
* SDIO function CIS tuple (unknown to the core)
*/
struct sdio_func_tuple {
struct sdio_func_tuple *next;
unsigned char code;
unsigned char size;
unsigned char data[0];
};
/*
* SDIO function devices
*/
struct sdio_func {
struct mmc_card *card; /* the card this device belongs to */
struct device dev; /* the device */
sdio_irq_handler_t *irq_handler; /* IRQ callback */
unsigned int num; /* function number */
unsigned char class; /* standard interface class */
unsigned short vendor; /* vendor id */
unsigned short device; /* device id */
unsigned max_blksize; /* maximum block size */
unsigned cur_blksize; /* current block size */
unsigned enable_timeout; /* max enable timeout in msec */
unsigned int state; /* function state */
#define SDIO_STATE_PRESENT (1<<0) /* present in sysfs */
u8 tmpbuf[4]; /* DMA:able scratch buffer */
unsigned num_info; /* number of info strings */
const char **info; /* info strings */
struct sdio_func_tuple *tuples;
};
#define sdio_func_present(f) ((f)->state & SDIO_STATE_PRESENT)
#define sdio_func_set_present(f) ((f)->state |= SDIO_STATE_PRESENT)
#define sdio_func_id(f) (dev_name(&(f)->dev))
#define sdio_get_drvdata(f) dev_get_drvdata(&(f)->dev)
#define sdio_set_drvdata(f,d) dev_set_drvdata(&(f)->dev, d)
#define dev_to_sdio_func(d) container_of(d, struct sdio_func, dev)
/*
* SDIO function device driver
*/
struct sdio_driver {
char *name;
const struct sdio_device_id *id_table;
int (*probe)(struct sdio_func *, const struct sdio_device_id *);
void (*remove)(struct sdio_func *);
struct device_driver drv;
};
#define to_sdio_driver(d) container_of(d, struct sdio_driver, drv)
/**
* SDIO_DEVICE - macro used to describe a specific SDIO device
* #vend: the 16 bit manufacturer code
* #dev: the 16 bit function id
*
* This macro is used to create a struct sdio_device_id that matches a
* specific device. The class field will be set to SDIO_ANY_ID.
*/
#define SDIO_DEVICE(vend,dev) \
.class = SDIO_ANY_ID, \
.vendor = (vend), .device = (dev)
/**
* SDIO_DEVICE_CLASS - macro used to describe a specific SDIO device class
* #dev_class: the 8 bit standard interface code
*
* This macro is used to create a struct sdio_device_id that matches a
* specific standard SDIO function type. The vendor and device fields will
* be set to SDIO_ANY_ID.
*/
#define SDIO_DEVICE_CLASS(dev_class) \
.class = (dev_class), \
.vendor = SDIO_ANY_ID, .device = SDIO_ANY_ID
extern int sdio_register_driver(struct sdio_driver *);
extern void sdio_unregister_driver(struct sdio_driver *);
/*
* SDIO I/O operations
*/
extern void sdio_claim_host(struct sdio_func *func);
extern void sdio_release_host(struct sdio_func *func);
extern int sdio_enable_func(struct sdio_func *func);
extern int sdio_disable_func(struct sdio_func *func);
extern int sdio_set_block_size(struct sdio_func *func, unsigned blksz);
extern int sdio_claim_irq(struct sdio_func *func, sdio_irq_handler_t *handler);
extern int sdio_release_irq(struct sdio_func *func);
extern unsigned int sdio_align_size(struct sdio_func *func, unsigned int sz);
extern u8 sdio_readb(struct sdio_func *func, unsigned int addr, int *err_ret);
extern u8 sdio_readb_ext(struct sdio_func *func, unsigned int addr, int *err_ret,
unsigned in);
extern u16 sdio_readw(struct sdio_func *func, unsigned int addr, int *err_ret);
extern u32 sdio_readl(struct sdio_func *func, unsigned int addr, int *err_ret);
extern int sdio_memcpy_fromio(struct sdio_func *func, void *dst,
unsigned int addr, int count);
extern int sdio_readsb(struct sdio_func *func, void *dst,
unsigned int addr, int count);
extern void sdio_writeb(struct sdio_func *func, u8 b,
unsigned int addr, int *err_ret);
extern void sdio_writew(struct sdio_func *func, u16 b,
unsigned int addr, int *err_ret);
extern void sdio_writel(struct sdio_func *func, u32 b,
unsigned int addr, int *err_ret);
extern int sdio_memcpy_toio(struct sdio_func *func, unsigned int addr,
void *src, int count);
extern int sdio_writesb(struct sdio_func *func, unsigned int addr,
void *src, int count);
extern unsigned char sdio_f0_readb(struct sdio_func *func,
unsigned int addr, int *err_ret);
extern void sdio_f0_writeb(struct sdio_func *func, unsigned char b,
unsigned int addr, int *err_ret);
extern mmc_pm_flag_t sdio_get_host_pm_caps(struct sdio_func *func);
extern int sdio_set_host_pm_flags(struct sdio_func *func, mmc_pm_flag_t flags);
#endif
line 169 is the last line of code before the #endif, but seeing it i just cant figure out whats wrong with it.
mmc_pm_flag_t type is not known to the compiler. Did you include the correct headers? If yes, check the headers and see if you need to enable some macro.
I found an implementation of AES for a project I'm doing.
However when i integrate it I'm getting the following errors during the build.
In file included from ff.h:26:0,
from disp.h:4,
from main.c:14:
aes.h:14:3: error: conflicting types for 'AesCtx'
aes.h:14:3: note: previous declaration of 'AesCtx' was here
aes.h:28:5: error: conflicting types for 'AesCtxIni'
aes.h:28:5: note: previous declaration of 'AesCtxIni' was here
aes.h:29:5: error: conflicting types for 'AesEncrypt'
aes.h:29:5: note: previous declaration of 'AesEncrypt' was here
aes.h:30:5: error: conflicting types for 'AesDecrypt'
aes.h:30:5: note: previous declaration of 'AesDecrypt' was here
The header file itself is:
// AES context structure
typedef struct {
unsigned int Ek[60];
unsigned int Dk[60];
unsigned int Iv[4];
unsigned char Nr;
unsigned char Mode;
} AesCtx;
// key length in bytes
#define KEY128 16
#define KEY192 24
#define KEY256 32
// block size in bytes
#define BLOCKSZ 16
// mode
#define EBC 0
#define CBC 1
// AES API function prototype
int AesCtxIni(AesCtx *pCtx, unsigned char *pIV, unsigned char *pKey, unsigned int KeyLen, unsigned char Mode);
int AesEncrypt(AesCtx *pCtx, unsigned char *pData, unsigned char *pCipher, unsigned int DataLen);
int AesDecrypt(AesCtx *pCtx, unsigned char *pCipher, unsigned char *pData, unsigned int CipherLen);
and then the respective C file uses.
int AesCtxIni(AesCtx *pCtx, unsigned char *pIV, unsigned char *pKey, unsigned int KeyLen, unsigned char Mode)
{
// Cut out code for brevity
}
int AesEncrypt(AesCtx *pCtx, unsigned char *pData, unsigned char *pCipher, unsigned int DataLen)
{
// Cut out code for brevity
}
int AesDecrypt(AesCtx *pCtx, unsigned char *pCipher, unsigned char *pData, unsigned int CipherLen)
{
// Cut out code for brevity
}
I know these errors usually occur because either the function hasn't been pre-declared or because it's slightly different to it's declaration, but I can't see a difference.
Any ideas?
What compiler are you using? My best guess that it's trying to say aes.h is being #included twice. Try adding header guards at the beginning and end of the aes.h:
#ifndef AES_H_
#define AES_H_
typedef struct {
...
int AesDecrypt(AesCtx *pCtx, unsigned char *pCipher, unsigned char *pData, unsigned int CipherLen);
#endif /* !AES_H_ */