mbedTLS pk parse error - c++

Could anyone help me find out why I get a -16000 (bad input data) on attempt to parse a public/private key from a unsigned char*?
Here's my code (edited for brevity):
DataPoint* GetPublicKey(mbedtls_pk_context* pppctx)
{
unsigned char* PKey = new unsigned char[16000];
if (mbedtls_pk_write_pubkey_pem(pppctx, PKey, 16000) != 0)
{
delete[] PKey;
return NULL;
}
DataPoint* Out = new DataPoint(strlen((char*)PKey) + 1); //Initializes an internal unsigned char* and size_t with the length of the key and the null byte
memcpy(Out->Data, PKey, Out->Length);
delete[] PKey;
return Out;
}
void GenRSA(mbedtls_rsa_context* rs)
{
mbedtls_rsa_gen_key(rs, mbedtls_ctr_drbg_random, &dctx, 2048, 65537);
}
int main()
{
mbedtls_pk_context pctx;
mbedtls_pk_init(&pctx);
mbedtls_pk_setup(&pctx, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA));
DataPoint* Key = GetPublicKey(&some_context_with_GenRSA_called);
cout << mbedtls_pk_parse_public_key(&pctx, Key->Data, Key->Length) << endl; //Returns -16000
return 0
}
And the same thing with the private key, what am I doing wrong?

The docs for mbedtls_pk_parse_public_key say:
On entry, ctx must be empty, either freshly initialised with mbedtls_pk_init() or reset with mbedtls_pk_free().
Your pseudo-code calls mbedtls_pk_setup on pctx. Perhaps this is the problem?
Can you check with other converters such as https://superdry.apphb.com/tools/online-rsa-key-converter to see if they can parse your PEM?

Related

C++ Parsing and Storing any kind of data

I'm working on a text-based a simple command processor for a microcontroller project (C and C++). It implements an "explicit setter" so to speak. It means that I store pointers to target memory locations and set them to the incoming data.
First of cource, I parse the data based a predefined set of syntactical rules:
"12345" -> string (char*)
12345 -> unsigned int
12.45 -> float
-123456 -> int (signed)
This is the method I've come up with:
void* CommandInterpreter::ParseArgumentValue(std::string token, size_t* ptrSize = nullptr) {
try {
void* value = NULL;
if(std::count(token.begin(), token.end(), '.') == 1) {
auto result = (float)std::atof(token.c_str());
value = malloc(sizeof(float));
ptrSize = sizeof(float);
memcpy(value, &result, sizeof(float));
} else if(token.front() == '"' && token.back() == '"') {
const char* result = token.substr(1, token.size()-2).c_str();
size_t size = (strlen(result) * sizeof(uint8_t)) + 1;
value = malloc(size);
ptrSize = size;
memcpy(value, result, size);
} else if(token.front() == '-') {
auto result = (int)std::atoi(token.c_str());
value = malloc(sizeof(int));
ptrSize = sizeof(int);
memcpy(value, &result, sizeof(int));
} else {
auto result = (unsigned int)std::stoul(token.c_str());
value = malloc(sizeof(unsigned int));
ptrSize = sizeof(unsigned int);
memcpy(value, &result, sizeof(unsigned int));
}
return value;
} catch(std::invalid_argument) {
//return NULL;
} catch(std::out_of_range) {
//return NULL;
}
}
I know it's not pretty, and it borders on bad-practice but it works.. however this will need to be freed after I process the value.
The actual setter-part looks like this:
auto setterdef = this->mDefinitions2[tokens[1]];
void* value = ParseArgumentValue(tokens[2]);
memcpy(setterdef.TargetPtr, value, setterdef.TargetSize);
if(memcmp(setterdef.TargetPtr, value, setterdef.TargetSize) != 0)
throw "COULD_NOT_SET";
free(value);
rbuilder.SetName("OK");
return rbuilder.Get();
The setter part works well, however I want to use the same function to parse an incoming parameter list and then store it in an std::map<std::string, void*> but this will keep the allocated memory even after the map is destroyed; as of right now I have a foreach in the destructor of my CommandParameterList class which frees the pointers in the map.. but it seems pretty odd to me.
My question would be.. how bad is this? And is there a better way to do this?
I know about std::any however, as far as I know I cannot just memcpy X amount of bytes from it, and I'd need to know the specific type to std::any_cast it.

c++ incorrect checksum for freed object-

I am getting this error (memory location varies between runs):
Freeing memory!
Image_Processing(6282,0x100091000) malloc: * error for object 0x1212121212121212: pointer being freed was not allocated
* set a breakpoint in malloc_error_break to debug
in this point it crashes : //delete m_data;
class Uint8Image {
public:
uint32_t m_w;
uint32_t m_h;
uint8_t *m_data;
Uint8Image(uint32_t w, uint32_t h): m_w(w), m_h(h), m_data(0)
{
m_data = new uint8_t(w*h);
}
Uint8Image(const Uint8Image &obj) ;
Uint8Image& operator = (const Uint8Image &D ) {
if(this != &D)
{
delete [] m_data;
m_w= D.m_w;
m_h = D.m_h;
m_data=new uint8_t(m_w * m_h); // deep copy the pointer data
}
return *this;
}
~Uint8Image()
{
std::cout << "Freeing memory!"<< std::endl;
delete m_data; // it crashes here
m_data = NULL;
}
};
class MeniscusFinderContext {
public:
MeniscusFinderContext( uint32_t m_a, uint32_t m_b):
{
m_input_image = new Uint8Image(m_a,m_b);
}
~MeniscusFinderContext()
{
delete m_input_image;
m_input_image = NULL;
}
Uint8Image m_input_image;};
//The function that calls:
// Taking input through option-parsing,
int main(int argc, char *argv[]{
const char *file_name = options[INPUT].arg;
std::ifstream file_stream(file_name,
std::ifstream::in | std::ifstream::binary);
char buf[256];
char *sEnd;
file_stream.getline(buf, sizeof(buf));
if(buf[0] != 'P' || buf[1] != '5') {
std::cerr << "invalid input PGM file" << std::endl;
return 1;
}
file_stream.getline(buf, sizeof(buf));
while(buf[0] == '#') file_stream.getline(buf, sizeof(buf));
uint32_t m_a = strtol(buf, &sEnd, 10);
uint32_t m_b = strtol(sEnd, &sEnd, 10);
MeniscusFinderContext M(m_a,m_b);
file_stream.getline(buf, sizeof(buf));
while(buf[0] == '#') file_stream.getline(buf, sizeof(buf));
if(atoi(buf) != 255) return 3;
file_stream.read((char *)M.m_input_image->m_data ,m_a * m_b);
if(!file_stream) {
std::cerr << "only got " << file_stream.gcount() << std::endl;
return 2;
}
file_stream.close();
return 0;
}
Edit: I'm running it and sometimes it runs while others it gives me the error. Seems to be at a random order. Any hints would be really helpful.
I already have checked all the related answers in stack overflow, but could nt figure it out.
new uint8_t(w*h);
This allocates exactly one uint8_t, whose initial value is w*h.
You probably intended:
new uint8_t[w*h];
Otherwise, this:
file_stream.read((char *)M.m_input_image->m_data ,m_a * m_b);
will immediately overrun this buffer. The same bug occurs several times in the shown code.
delete m_data;
Stuff allocated with new[] should be deallocated with delete[].
In general, your overall approach is very error-prone. Instead of manually handling memory, in this fashion, you should be using std::vector, and iterators. Correct usage of C++'s containers greatly reduces the possibility of making these kinds of bugs.

Implementing cdbpp library for string values

I am trying to implement the cdbpp library from chokkan. I am facing some problems when I was trying to implement the same for values with data type of strings.
The original code and documentation can be found here:
http://www.chokkan.org/software/cdbpp/ and the git source code is here: https://github.com/chokkan/cdbpp
This is what I have so far:
In the sample.cpp (from where i am calling the main function), I modified the build() function:
bool build()
{
// Open a database file for writing (with binary mode).
std::ofstream ofs(DBNAME, std::ios_base::binary);
if (ofs.fail()) {
std::cerr << "ERROR: Failed to open a database file." << std::endl;
return false;
}
try {
// Create an instance of CDB++ writer.
cdbpp::builder dbw(ofs);
// Insert key/value pairs to the CDB++ writer.
for (int i = 1;i < N;++i) {
std::string key = int2str(i);
const char* val = "foobar"; //string value here
dbw.put(key.c_str(), key.length(), &val, sizeof(i));
}
} catch (const cdbpp::builder_exception& e) {
// Abort if something went wrong...
std::cerr << "ERROR: " << e.what() << std::endl;
return false;
}
return true;
}
and in cdbpp.h file, i modified the put() function as :
void put(const key_t *key, size_t ksize, const value_t *value, size_t vsize)
{
// Write out the current record.
std::string temp2 = *value;
const char* temp = temp2.c_str();
write_uint32((uint32_t)ksize);
m_os.write(reinterpret_cast<const char *>(key), ksize);
write_uint32((uint32_t)vsize);
m_os.write(reinterpret_cast<const char *>(temp), vsize);
// Compute the hash value and choose a hash table.
uint32_t hv = hash_function()(static_cast<const void *>(key), ksize);
hashtable& ht = m_ht[hv % NUM_TABLES];
// Store the hash value and offset to the hash table.
ht.push_back(bucket(hv, m_cur));
// Increment the current position.
m_cur += sizeof(uint32_t) + ksize + sizeof(uint32_t) + vsize;
}
Now the I get the correct value if the string is less than or equal to 3 characters(eg: foo will return foo). If it is greater than 3 it gives me the correct string up to 3 characters then garbage value(eg. foobar gives me foo�`)
I am a little new to c++ and I would appreciate any help you could give me.
(moving possible answer in comment to real answer)
vsize as passed into put is the size of an integer when it should be the length of the value string.

How to handle PAM_AUTHTOK_RECOVERY_ERR return value from pam_authenticate for valid user and password?

I'm trying to write some server which authenticates clients using linux pam. I wrote the following class:
class Pam
{
public:
Pam(const char *module, const char *username)
{
mConv.appdata_ptr = nullptr;
mConv.conv = &convCallback;
const int res = pam_start("system-auth", username, &mConv, &mPamHandle);
if (res != PAM_SUCCESS)
throw std::runtime_error("Failed to initialize PAM");
}
bool authenticate(char *passwd)
{
pam_response *resp = static_cast<pam_response*>(malloc(sizeof(pam_response)));
resp->resp = passwd;
resp->resp_retcode = 0;
mConv.appdata_ptr = resp;
const int res = pam_authenticate(mPamHandle, 0);
log(res);
return res == PAM_SUCCESS;
}
~Pam()
{
if (mPamHandle)
pam_end(mPamHandle, PAM_SUCCESS);
mPamHandle = nullptr;
}
private:
static int convCallback (int msgId, const pam_message **msg, pam_response **resp, void *appData)
{
*resp = static_cast<pam_response*>(appData);
return PAM_SUCCESS;
}
private:
pam_handle_t *mPamHandle = nullptr;
pam_conv mConv;
};
Which then is used like:
Pam pam("system-auth", username);
if (pam.authenticate(passwd))
return true;
// error handling code here
I discovered that pam_authenticate returns PAM_AUTHTOK_RECOVERY_ERR for valid user/password. Possible return values documented in the man page and on the linux-pam.org http://www.linux-pam.org/Linux-PAM-html/adg-interface-by-app-expected.html#adg-pam_authenticate do not contain this value at all. Documentation says that it can be returned by pam_chauthtok and this means:
PAM_AUTHTOK_RECOVERY_ERR
A module was unable to obtain the old authentication token.
And it's still unclear what does it means in case of authentication. I've tried to run code both as normal user and as root the result was the same.
What's happening is that you're seeing 0 as the value of appData in convCallback, which is where the error is coming from - the reply data is empty, which means bad conversation, which causes the PAM_AUTHTOK_RECOVERY_ERR return value. This is based on reading the support.c file in the current code for the PAM-Linux source code.
Ok, couple of issues.
You can't reassign the conversation appdata_ptr value after initialization - the value of the pointer should be considered a constant after the invocation of pam_start. You should pass in a value there that will never change. If you checked the conversation function you would have noticed that the value of appData is 0.
You must assume that the value being put into the reply is owned by the calling routine - i.e. you'll have to strdup the password string (with all the evil that is connected to that).
With both of these in mind, I slightly altered your code to the following, which should address your problems (again, this is simplified code):
class Pam
{
public:
Pam(const char *module, const char *username)
{
mConv.appdata_ptr = (void *)(this);
mConv.conv = &convCallback;
const int res = pam_start(module, username, &mConv, &mPamHandle);
if (res != PAM_SUCCESS)
throw std::runtime_error("Failed to initialize PAM");
}
bool authenticate(char *passwd)
{
mPassword = passwd;
const int res = pam_authenticate(mPamHandle, 0);
log(res);
return res == PAM_SUCCESS;
}
~Pam()
{
if (mPamHandle)
pam_end(mPamHandle, PAM_SUCCESS);
mPamHandle = 0;
}
private:
static int convCallback (int msgId, const pam_message **msg, pam_response **resp, void *appData)
{
Pam *me = static_cast<Pam *>(appData);
pam_response *reply = static_cast<pam_response *>(calloc(1, sizeof(pam_response)));
reply->resp = strdup(me->mPassword);
reply->resp_retcode = 0;
*resp = reply;
return PAM_SUCCESS;
}
private:
pam_handle_t *mPamHandle = 0;
pam_conv mConv;
const char *mPassword = 0;
};

How to cast from char pointer to custom object pointer

I'm using leveldb to store key-value pairs of integer and MyClass objects. Actually, a key can contain more then one of theses objects.
The problem I have appears when retrieving the data from the database. It compiles, however the values of the MyClass members are not the one I put into the database.
std::string value;
leveldb::Slice keySlice = ANYKEY;
levelDBObj->Get(leveldb::ReadOptions(), keySlice, &value);
The std::string value1 can now contain only one MyClass object or more. So how do I get them?
I already tried the following which didn't work;
1.) directly typecasting and memcpy
std::vector<MyClass> vObjects;
MyClass* obj = (MyClass*)malloc( value.size());
memcpy((void*)obj, (void*) (value.c_str()), value.size());
MyClass dummyObj;
int numValues = value.size()/sizeof(MyClass);
for( int i=0; i<numValues; ++i) {
dummyObj = *(obj+i);
vObjects.push_back(dummyObj);
}
2.) reinterpret_cast to void pointer
MyClass* obj = (MyClass*)malloc( value.size());
const void* vobj = reinterpret_cast<const void*>( value.c_str() );
int numValues = value.size()/sizeof(MyClass);
for( int i=0; i<numValues; ++i) {
const MyClass dummyObj = *(reinterpret_cast<const MyClass*>(vobj)+i);
vObjects.push_back(dummyObj);
}
MyClass is a collection of several public members, e.g. unsigned int and unsigned char and it has a stable size.
I know that there are similar problems with only one object. But in my case the vector can contain more then one and it comes from the leveldb database.
EDIT: SOLUTION
I wrote (de)serialization method for MyClass which then made it working. Thanks for the hint!
void MyClass::serialize( char* outBuff ) {
memcpy(outBuff, (const void*) &aVar, sizeof(aVar));
unsigned int c = sizeof(aVar);
memcpy(outBuff+c, (const void*) &bVar, sizeof(bVar));
c += sizeof(bVAr);
/* and so on */
}
void MyClass::deserialize( const char* inBuff ) {
memcpy((void*) &aVar, inBuff, sizeof(aVar));
unsigned int c = sizeof(aVar);
memcpy((void*) &aVar, inBuff+c, sizeof(aVar));
c += sizeof(aVar);
/* and so on */
}
The get method is as follows (put analogously):
int getValues(leveldb::Slice keySlice, std::vector<MyObj>& values) const {
std::string value;
leveldb::Status status = levelDBObj->Get(leveldb::ReadOptions(), keySlice, &value);
if (!status.ok()) {
values.clear();
return -1;
}
int nValues = value1.size()/sizeof(CHit);
MyObj dummyObj;
for( int i=0; i<nValues; ++i) {
dummyObj.deserialize(value.c_str()+i*sizeof(MyObj));
values.push_back(dummyObj);
}
return 0;
}
You have to serialize your class... otherwise, you're just taking some memory and writing it in leveldb. Whatever you get back is not only going to be different, but it will probably be completely useless too. Check out this question for more info on serialization: How do you serialize an object in C++?
LevelDB does support multiple objects under one key, however, try to avoid doing that unless you have a really good reason. I would recommend that you hash each object with a unique hash (see Google's CityHash if you want a hashing function) and store the serialized objects with their corresponding hash. If your objects is a collection in itself, then you have to serialize all of your objects to an array of bytes and have some method that allows you to determine where each object begins/ends.
Update
A serializable class would look something like this:
class MyClass
{
private:
int _numeric;
string _text;
public:
// constructors
// mutators
void SetNumeric(int num);
void SetText(string text);
static unsigned int SerializableSize()
{
// returns the serializable size of the class with the schema:
// 4 bytes for the numeric (integer)
// 4 bytes for the unsigned int (the size of the text)
// n bytes for the text (it has a variable size)
return sizeof(int) + sizeof(unsigned int) + _text.size();
}
// serialization
int Serialize(const char* buffer, const unsigned int bufferLen, const unsigned int position)
{
// check if the object can be serialized in the available buffer space
if(position+SerializableSize()>bufferLen)
{
// don't write anything and return -1 signaling that there was an error
return -1;
}
unsigned int finalPosition = position;
// write the numeric value
*(int*)(buffer + finalPosition) = _numeric;
// move the final position past the numeric value
finalPosition += sizeof(int);
// write the size of the text
*(unsigned int*)(buffer + finalPosition) = (unsigned int)_text.size();
// move the final position past the size of the string
finalPosition += sizeof(unsigned int);
// write the string
memcpy((void*)(buffer+finalPosition), _text.c_str(), (unsigned int)_text.size());
// move the final position past the end of the string
finalPosition += (unsigned int)_text.size();
// return the number of bytes written to the buffer
return finalPosition-position;
}
// deserialization
static int Deserialize(MyClass& myObject,
const char* buffer,
const unsigned int buffSize,
const unsigned int position)
{
insigned int currPosition = position;
// copy the numeric value
int numeric = *(int*)(buffer + currentPosition);
// increment the current position past the numeric value
currentPosition += sizeof(int);
// copy the size of the text
unsigned int textSize = *(unsigned int*)(buffer + currentPosition);
// increment the current position past the size of the text
currentPosition += sizeof(unsigned int);
// copy the text
string text((buffer+currentPosition), textSize);
if(currentPosition > buffSize)
{
// you decide what to do here
}
// Set your object's values
myObject.SetNumeric(numeric);
myObject.SetText(text);
// return the number of bytes deserialized
return currentPosition - position;
}
};