I am trying to use the PEM_read_bio function to get data from a file.
The version of SSLeay we are using is from 1997, so documentation is a bit thin on the ground. Thankfully in this case it seems there is a matching function documented here: https://www.openssl.org/docs/man1.1.0/crypto/PEM_read_bio.html
I originally tried this:
char ** names;
char ** headers;
unsigned char ** data;
long len;
BIO *in = BIO_new_file("C:\\filename.txt", "r");
if (!in)
{
// error
}
else
{
int result = PEM_read_bio(in, names, headers, data, &len);
}
BIO_free(in);
OPENSSL_free(names);
OPENSSL_free(headers);
OPENSSL_free(data);
However this results in a run-time check failure: The variable 'names' is being used without being initialized.
The documentation mentions OPENSSL_malloc( num ) is used to initialize memory, but it fails to mention whether it does this behind the scenes, or the user does it.
OPENSSL_malloc is similar in usage to C's malloc, but how are we supposed to know how much memory to allocate in advance, before reading the file?
I have tried the following at the beginning:
char ** names = reinterpret_cast<char **>(OPENSSL_malloc(2));
char ** headers = reinterpret_cast<char **>(OPENSSL_malloc(2));
unsigned char ** data = reinterpret_cast<unsigned char **>(OPENSSL_malloc(2));
long len;
This results in apparently random data.
The documentation you linked to says:
The name, header and data pointers are allocated via OPENSSL_malloc() and should be freed by the caller via OPENSSL_free() when no longer needed.
That means PEM_read_bio() calls OPENSSL_malloc() for you, and then you call OPENSSL_free() on the allocated memory it returns when you are doing with it.
You are passing uninitialized pointers to PEM_read_bio(), that is why it is failing. The name, header and data parameters are all output parameters. You need to pass in the addresses of your own pointer variables to receive the memory that PEM_read_bio() allocates for you, eg:
char *name;
char *headers;
unsigned char *data;
long len;
BIO *in = BIO_new_file("C:\\filename.txt", "r");
if (!in)
{
// error
}
else
{
int result = PEM_read_bio(in, &name, &headers, &data, &len);
if (!result)
{
// error
}
else
{
...
OPENSSL_free(name);
OPENSSL_free(headers);
OPENSSL_free(data);
}
BIO_free(in);
}
Related
I'm having a weird and unexpected result in my code and I'd like your support to explain me what happens here.
I have a structure of a confiration :
struct sConfig {
const char* ssid;
const char* password;
}
I'm loading this configuration using LittleFS from a deserialized json :
config.ssid = json["ssid"]; // so this is coming from the FS in a json file
config.password = json["password"]; // so this is coming from the FS in a json file
So far, all is fine, I can print out the value using
Serial.println(config.ssid);
I'm then calling an internal void function
startWiFi(config.ssid, config.password);
void startWiFi(const char* ssid, const char* psswd) {
Serial.println(ssid);
Serial.println(psswd);
}
As a result, the console returns :
⸮
and
?:⸮?#⸮8⸮?<9⸮?⸮8⸮?:⸮?#⸮8⸮?<9⸮?⸮8⸮?:⸮?#⸮8⸮?<9⸮?⸮8⸮?.:⸮?#⸮
What can be wrong in my variables ?
Please help me as I'm stuck.
Thanks a lot.
To fix the issue I'd avoid copying a pointer and copy the actual data.
So, instead of config.password = json["password"];
I'd declare ssid and password as char arrays and copy the values from the json with strncpy()
struct sConfig {
char ssid[32];
char password[64];
}
or I'd allocate them on the spot with a custom copy function
char * myCopy (char *destination, const char *source)
{
// I'm using 64 because is the max length of WPA2-PSK passwords
size_t len = strnlen(destination, 64);
destination = malloc((num + 1) * sizeof(char));
strncpy(destination, source, num);
return destination;
}
....
myCopy(config.ssid, json["ssid"]);
myCopy(config.password, json["password"]);
What's probably happening here is a use-after-free bug.
At config.ssid = json["ssid"] you copy a pointer to the internal memory of the json object. It's probably valid at the time of that copy (so the print succeeds), but when the json changes its state or gets deallocated, you get garbage at that memory address.
The solution is - as suggested in the other answer - copy the whole string and not just its address.
I'm trying to read the content of a file from an enclave using OCalls.
enclave.edl:
untrusted {
void ocall_print_string([in, string] const char *str);
void ocall_read_IMA_file([in, string] const char *filename, [out] char *buf, [out] int *size);
};
enclave.cpp:
void printf(const char *fmt, ...) {
ocall_print_string(fmt);
}
void read_IMA_file(const char *filename, char *buf, int *size) {
ocall_read_IMA_file(filename, buf, size);
printf(buf);
}
//whereas the read_IMA_file function is called with
char *buf;
int size;
read_IMA_file("test.txt", buf, &size);
implementation of ocall functions in the application:
void ocall_print_string(const char *str) {
printf("%s\n", str);
}
void ocall_read_IMA_file(const char *filename, char *content, int *size) {
content = (char*) malloc(sizeof(char) * 10);
memset(content, '\0', sizeof(char) *10);
char tmp[] = "1234567890";
copy(&tmp[0], &tmp[9], content);
cout << content << endl;
}
But the result I receive is the following:
123456789 (null)
I'm not sure what I'm doing wrong?
In the above program, the "read_IMA_file" trusted function is called with pointer variable(OUT pointer) of type character.Here we are passing the pointer variable without any memory allocation.
"read_IMA_file" initiate a OCall that allocate memory and do "Copy" operation.Now the allocated memory is valid within the untrusted region. So we are getting expected result for the "cout<
Since there is no trusted memory allocated for "content"(before calling Ocall), no copy back operation happens in "OUT" pointer during Ocall returns.
So "buf" doesn't contain any valid data while doing "print(buf)" after Ocall returns in trusted region.
Please try with valid OUT pointer to character buffer(with some memory allocation) or IN and OUT pointer to String buffer.
If you expect it to output 1234567890, then you may need to malloc(11) instead of malloc(10), plus the way you are using copy may contain a bug too.
copy(&tmp[0], &tmp[9], content);
is copying 123456789 to the content, it exclude the the last iterator &tmp[9] as I understand. For more detail, you may want to look at: http://www.cplusplus.com/reference/algorithm/copy/
Also, I think you are not reading in any content from file "test.txt" either.
I have a program that employs an entity-component-system framework. Essentially this means that I have a collection of entities that have various components attached to them. Entities are actually just integer ID numbers, and components are attached to them by mapping the component to the specified ID number of the entity.
Now, I need to store collections of entities and the associated components to a file that can be modified later on, so basically I need a saving and loading functionality. However, being somewhat a newcomer to C++, I have hard time figuring out how to exactly do this.
Coming from Java and C#, my first choice would be to serialize the objects into, say, JSON, and then deserialize them when the JSON is loaded. However, C++ does not have any reflection features. So, the question is: how do I save and load C++ objects? I don't mean the actual file operations, I mean the way the objects and structs should be handled in order to preserve them between program launches.
One way of doing is to create Persistent Objects in C++, and store the your data.
check out the following links:
C++ object persistence library similar to eternity
http://sourceforge.net/projects/litesql/
http://en.wikipedia.org/wiki/ODB_(C%2B%2B)
http://drdobbs.com/cpp/184408893
http://tools.devshed.com/c/a/Web-Development/C-Programming-Persistence/
C++ doesn't support persistence directly (there are proposals for adding persistence and reflection to C++ in the future). Persistence support is not as trivial as it may seem at first. The size and memory layout of the same object may vary from one platform to another. Different byte ordering, or endian-ness, complicate matters even further. To make an object persistent, we have to reserve its state in a non-volatile storage device. ie: Write a persistent object to retain its state outside the scope of the program in which it was created.
Other Way, is to store the objects into an array, then push the array buffer to a file.
The advantage are that the disk platters don't have waste time ramping up and also the writing can be performed contiguously.
You can increase the performance by using threads. Dump the objects to a buffer, once done trigger a thread to handle the output.
Example:
The following code has not been compiled and is for illustrative purposes only.
#include <fstream>
#include <algorithm>
using std::ofstream;
using std::fill;
#define MAX_DATA_LEN 1024 // Assuming max size of data be 1024
class stream_interface
{
virtual void load_from_buffer(const unsigned char *& buf_ptr) = 0;
virtual size_t size_on_stream(void) const = 0;
virtual void store_to_buffer(unsigned char *& buf_ptr) const = 0;
};
struct Component
: public stream_interface,
data_length(MAX_DATA_LEN)
{
unsigned int entity;
std::string data;
const unsigned int data_length;
void load_from_buffer(const unsigned char *& buf_ptr)
{
entity = *((unsigned int *) buf_ptr);
buf_ptr += sizeof(unsigned int);
data = std::string((char *) buf_ptr);
buf_ptr += data_length;
return;
}
size_t size_on_stream(void) const
{
return sizeof(unsigned int) + data_length;
}
void store_to_buffer(unsigned char *& buf_ptr) const
{
*((unsigned int *) buf_ptr) = entity;
buf_ptr += sizeof(unsigned int);
std::fill(buf_ptr, 0, data_length);
strncpy((char *) buf_ptr, data.c_str(), data_length);
buf_ptr += data_length;
return;
}
};
int main(void)
{
Component c1;
c1.data = "Some Data";
c1.entity = 5;
ofstream data_file("ComponentList.bin", std::ios::binary);
// Determine size of buffer
size_t buffer_size = c1.size_on_stream();
// Allocate the buffer
unsigned char * buffer = new unsigned char [buffer_size];
unsigned char * buf_ptr = buffer;
// Write / store the object into the buffer.
c1.store_to_buffer(buf_ptr);
// Write the buffer to the file / stream.
data_file.write((char *) buffer, buffer_size);
data_file.close();
delete [] buffer;
return 0;
}
I need to read a stream out of a binary file from a function. I'd like to call it by reference of that char * to have a pointer to the start of the stream in the end. However, Every attempt of mine, did either not change the pointer, or caused an Memory Access Violation.
I call the method from another function.
Here the calling function:
APP_ERROR EncryptionHandler::encryptFile(char *file)
{
char *i_Stream = ""; // I get a compiler error if I dont initialize this
if(this->readFileStream("picture.png", i_Stream) != OPERATION_SUCCESSFUL) // Call the function and return a custom error, if the function does so
return ERROR_FILE_READING;
}
Here the function to read the file
APP_ERROR EncryptionHandler::readFileStream(char *fileName, char *Stream)
{
char *fileStream;
FILE *file = fopen(fileName, "rb");
// Some logic to get the file size
fileStream = new char[maxFileSize];
fread(fileStream, 1, maxFileSize, file); // Fill the stream with the fread function
fclose(file);
Stream = fileStream; // Set the given Pointer to my fileStream pointer
return OPERATION_SUCCESSFUL;
}
How ever in the calling function, the Variable i_Stream has never changed. It's still pointing to "" which causes problems in my program, later
I don't get this, as I set the given pointer = my fileStream pointer
However following methods didn't work aswell:
this->readFileStream("picture.png", char &i_Stream);
i_Error EncryptionHandler::readFileStream(char *fileName, char **Stream)
this->readFileStream("picture.png", char *i_Stream);
i_Error EncryptionHandler::readFileStream(char *fileName, char &Stream)
Procedures like memcpy aren't the right thing I think, as I've already got this pointer to my Stream. And they caused Access Violation Errors aswell...
There must be an easy way to give that stream pointer from within my file reading function to my calling methods variable...
I cannot use the return value of the function, because I am using my own Error system, as you can see...
It is also binary Data and the use of any strings is not welcome.
So what is the proper way of calling a char array by reference?
You should declare EncryptionHandler::readFileStream() as
APP_ERROR EncryptionHandler::readFileStream(char *fileName, char *&Stream)
Note the type of parameter Stream. With reference of pointer, you can pass the change of Stream inside readFileStream() back to caller.
Without the reference, the pointer is simply copied into readFileStream().
In addition to what #timrau said, I see a memory allocation problem. I don't see any code that allocates memory to hold the data that you are reading from the file. Something like the code below should work.
PP_ERROR EncryptionHandler::readFileStream(char *fileName, char*& Stream)
{
char *fileStream;
FILE *file = fopen(fileName, "rb");
// Some logic to get the file size
// Allocate memory for the data.
fileStream = new char[maxFileSize];
fread(fileStream, 1, maxFileSize, file); // Fill the stream with the fread function
fclose(file);
Stream = fileStream; // Set the given Pointer to my fileStream pointer
return OPERATION_SUCCESSFUL;
}
You can simplify the function a little bit by just using Stream.
PP_ERROR EncryptionHandler::readFileStream(char *fileName, char*& Stream)
{
FILE *file = fopen(fileName, "rb");
// Some logic to get the file size
// Allocate memory for the data.
Stream = new char[maxFileSize];
fread(Stream, 1, maxFileSize, file); // Fill the stream with the fread function
fclose(file);
return OPERATION_SUCCESSFUL;
}
I hava a class like:
class SomeClass
{
void initFromBuffer(void* buffer,int length);
void initFromString(const std::string& str);
}
Using tolua++, got the binding like:
static int SomeClass_initFromBuffer00(lua_State* tolua_S)
{
SomeClass* self = (SomeClass*) tolua_tousertype(tolua_S,1,0);
void* buffer = ((void*) tolua_touserdata(tolua_S,2,0));
int length = ((int) tolua_tonumber(tolua_S,3,0));
self->initFromBuffer(buffer,length);
}
and:
static int SomeClass_initFromString00(lua_State* tolua_S)
{
SomeClass* self = (SomeClass*) tolua_tousertype(tolua_S,1,0);
const std::string str = ((const std::string) tolua_tocppstring(tolua_S,2,0));
self->initFromString(str);
tolua_pushcppstring(tolua_S,(const char*)str);
}
Now,i want to pass binary data from lua to c++,the binary has '\0' in it,so if i use initFromString to pass it, the binary data will be trimed. But if i use initFromBuffer to pass it, i got bad ptr at `void* buffer = ((void*) tolua_touserdata(tolua_S,2,0));, the pointer is null.
So, how could i pass binary string from lua to c++?
Maybe you should stop using Tolua's bad APIs and use plain Lua's actually good APIs. Both std::string and Lua strings are capable of storing embedded null characters. The only reason tolua_tocppstring causes truncation is because the function name is a lie. It doesn't convert it to a C++ string; it converts it to a C string, a const char*.
The correct answer is to use the proper API function:
std::string fromLuaStack(lua_State *lua, int stackIx)
{
size_t len;
const char *str = lua_tolstring(lua, stackIx, &len);
return std::string(str, len);
}
Similarly, you can use lua_pushlstring to push a std::string onto the stack.
It's unfortunate that Tolua doesn't have better documentation, as there may be a function to do this all directly. If there is, I couldn't find it.