Why would RSA_size crash? - c

I'm trying to use the OpenSSL crypto lib and it's crashing in a call that's a staple in every example I've seen. Here's how it's set up:
BIO* bp = BIO_new_mem_buf(_publicKey, -1); // Create a new memory buffer BIO.
RSA* pubKey = PEM_read_bio_RSA_PUBKEY(bp, 0, 0, 0); // And read the RSA key from it.
unsigned char encryptedRandKey[RSA_size(pubKey)];
BIO_free(bp);
_publicKey is a null-terminated character string containing a PEM-formatted RSA key (with the -----BEGIN XXX----- and so forth). It crashes with bad access in RSA_size.
It doesn't matter if I remove the BIO_free.
Any ideas? Thanks!

You need to check the return value of PEM_read_bio_RSA_PUBKEY() to make sure it is non-null. Most likely the contents of _publicKey are not quite a correctly formatted key and as a consequence pubKey is NULL.

Try PEM_read_bio_RSAPublicKey instead of PEM_read_bio_RSA_PUBKEY.

Related

jansson json_decref unexpected behavior

I am using the jansson library for a C project.
I have some problem understanding how to use the decref. Shall it be used after each new json_t parameter or not? As I understand jansson will borrow references to make this simpler.
If I run this program and check the values of a_id and a_test they are the same. I expected error or null for a_test.
I tried the same idea but then I added decref for json_acc and json_param but it crashed before I could even read the 1:th value. I was assuming a crash but not until a_test.
This is part of a bigger project but I try to add an example to show the essentials.
API side:
json_t* parObj;
void loadFile(char* path)
{
json_error_t error;
parObj = json_load_file(path, 0, &error);
}
int getAccountId(char* id)
{
json_t* json_acc = json_object_get(parObj, "accounts");
json_t* json_param = json_object_get(json_acc, id);
return json_integer_value(json_param);
}
void cleanJson()
{
json_decref(parObj);
}
Caller side:
loadFile("/home/jacob/accountDump.json");
int a_id = getAccountId("10");
cleanJson();
int a_test = getAccountId("10");
I did misunderstood how it is supposed to work, I assumed that decref would also set the memory to zero.
The API will remove the references and make it a free memory but as long as no one writes there or memset it to zero and the pointer is not set to null I can still read the values from that pointer.

how to store public key as c array

I've been looking for an answer for this for a while so i though i might aswell post what I've found.
I'm using openssl to sign and verify license using private key to sign and public key to verify.
since I'm sending the public key to the client for verification, I can't give it to him and ask for path to key, because he can change the public key and encrypt the message using his own private/public keys.
the solution: store the public key inside the C program as an array.
now i need to change my code of reading the public key from:
EVP_PKEY *public_key = NULL;
public_key_fd = fopen( public_key_path, "r" );
if ( !public_key_fd )
// something went wrong
PEM_read_PUBKEY( public_key_fd, &public_key, NULL, NULL );
fclose( public_key_path );
to something that uses a string instead of a file.
first we need to understand what does the look like, using cat:
cat public_key.pem
we get
---- BEGIN PUBLIC KEY ----
AAAAB3NzaC1yc2EAAAABJQAAAQB/nAmOjTmezNUDKYvEeIRf2YnwM9/uUG1d0BYs
c8/tRtx+RGi7N2lUbp728MXGwdnL9od4cItzky/zVdLZE2cycOa18xBK9cOWmcKS
0A8FYBxEQWJ/q9YVUgZbFKfYGaGQxsER+A0w/fX8ALuk78ktP31K69LcQgxIsl7r
NzxsoOQKJ/CIxOGMMxczYTiEoLvQhapFQMs3FL96didKr/QbrfB1WT6s3838SEaX
fgZvLef1YB2xmfhbT9OXFE3FXvh2UPBfN+ffE7iiayQf/2XR+8j4N4bW30DiPtOQ
LGUrH1y5X/rpNZNlWW2+jGIxqZtgWg7lTy3mXy5x836Sj/6L
---- END PUBLIC KEY ----
I've read this char by char to understand where are the '\n' and other invisible characters and what I've found is that each line ends with '\n'
so what we get as an array for C will be:
char *key_string = "---- BEGIN PUBLIC KEY ----\nAAAAB3NzaC1yc2EAAAABJQAAAQB/nAmOjTmezNUDKYvEeIRf2YnwM9/uUG1d0BYs\nc8/tRtx+RGi7N2lUbp728MXGwdnL9od4cItzky/zVdLZE2cycOa18xBK9cOWmcKS\n0A8FYBxEQWJ/q9YVUgZbFKfYGaGQxsER+A0w/fX8ALuk78ktP31K69LcQgxIsl7r\nNzxsoOQKJ/CIxOGMMxczYTiEoLvQhapFQMs3FL96didKr/QbrfB1WT6s3838SEaX\nfgZvLef1YB2xmfhbT9OXFE3FXvh2UPBfN+ffE7iiayQf/2XR+8j4N4bW30DiPtOQ\nLGUrH1y5X/rpNZNlWW2+jGIxqZtgWg7lTy3mXy5x836Sj/6L\n---- END PUBLIC KEY ----\n";
and The code needed to read a key from a char array is:
EVP_PKEY *public_key = NULL;
BIO *bio;
bio = BIO_num_mem_buf( key_string, strlen( key_string ) );
PEM_read_bio_PUBKEY( bio, &public_key, NULL, NULL );
explaination: PEM_read_PrivateKey() is a wrapper around PEM_ASN1_read() (which reads an arbitrary ASN.1 object from a
PEM-encoded blob) and d2i_PrivateKey() (which knows how to read a private key blob specifically).
PEM_ASN1_read() simply creates a BIO from the FILE* that you give it, and calls PEM_ASN1_read_bio(). If
you want, you can instead create a BIO from your string using something like BIO_new_mem_buf() and call
PEM_ASN1_read_bio() yourself. (A BIO is an openssl object that's like a more general-purpose FILE*.)
BTW, if your keys are stored in a database, there's probably no need for them to be PEM-encoded; you can save a
bit of space and time by storing them in DER format and calling d2i_PrivateKey() directly. (PEM format is
more or less just base64-encoded DER.) There's a FAQ entry on this:
http://www.openssl.org/support/faq.html#PROG3

CryptDecodeObjectEx Bad Tag ERROR (0x8009310b)

I have a .cer file. I can read it and write a buffer via ReadFile() function.
Now I have buffer and datalen which I had.
And I use that buffer and len for calling CryptDecodeObjectEx() function like below line
if ( !CryptDecodeObjectEx( X509_ASN_ENCODING,
X509_PUBLIC_KEY_INFO,
(BYTE* )pemPubKey,
readLen,
CRYPT_DECODE_ALLOC_FLAG,
NULL,
&publicKeyInfo,
(DWORD *)&publicKeyInfoLen ) )
But when I run it through debug, I get 0x8009310B error code via GetLastError() func.
How can I fix it?
Thanks for your advice.
Additional Information
If I use X509_ANY_STRING instead of X509_PUBLIC_KEY_INFO; it works.
But it does not fill my publicKeyInfo struct. Because of that I
cannot get public key in it .
I have a DER formatted certificate.

OpenAES/OpenSSL compatibility

I'm trying to use both OpenAES and OpenSSL in C, this way:
Application 1 encodes a password using OpenAES
Application 2 decodes the password using OpenSSL
The problem is that I can't decode it, actually I'm quite surprised as OpenAES generates a
different block each time when OpenSSL or any other AES implementation I've seen always generate
the same block.
Another difference I noticed is that the OpenAES generated block is 48 bytes, when OpenSSL generates 16.
This is how I encrypt the string (OpenAES):
pCtx = oaes_alloc();
if (pCtx == NULL)
return FALSE;
oRet = oaes_key_import(pCtx, sKey, szKey);
if (oRet != OAES_RET_SUCCESS)
{
return FALSE;
}
// Get the required buffer size
oRet = oaes_encrypt(pCtx, (const uint8_t*)csSource, szLen, NULL, pOutLen);
if (oRet != OAES_RET_SUCCESS)
{
oaes_free(&pCtx);
return FALSE;
}
*ppOut = (char*)calloc(*pOutLen, sizeof(char));
oRet = oaes_encrypt(pCtx, (const uint8_t*)csSource, szLen, (uint8_t*)*ppOut, pOutLen);
if (oRet != OAES_RET_SUCCESS)
{
oaes_free(&pCtx);
free(*ppOut);
return FALSE;
}
oaes_free(&pCtx);
And this is how I decrypt it (OpenSSL):
AES_KEY kDecrypt;
AES_set_decrypt_key(sKey, 128, &kDecrypt);
AES_decrypt(pEncoded, pDecoded, &kDecrypt);
sKey being the key generated with OpenAES
pEncoded the crypted block from OpenAES
pDecoded the output data.
I can't put my finger on the problem yet...
Is there a particular way to use OpenAES so the result can be decrypted by OpenSSL, or is it just not compatible?
OpenAES prefixes the encrypted data with a OpenAES specific header, followed by the iv and then the encrypted data (+ padding).
As the IV seems to be generated randomly by OpenAES that explains why the data differs with each encrypt.

openssl create rsa key pair in C and export it

I want to create a RSA key pair in C/C++ and export it to a string to work with it.
I managed to create the key
rsa = RSA_generate_key(bits, exp, NULL, NULL);
if(RSA_check_key(rsa)!=1){
std::cout << "Error while checking key" << std::endl << std::flush;
}
pkey = EVP_PKEY_new();
EVP_PKEY_assign_RSA(pkey, rsa);
From this point I can write the private and public key to a file with PEM_write_PUBKEY() and PEM_write_PrivateKey(). But what I want to do is to get the private and public key from pkey directly into a variable, preferable in the PEM format. I already looked around but couldn't find the right function. Any hints?
If you really need the PEM representation, then PEM_write_bio_RSA_PUBKEY() and PEM_write_bio_RSAPrivateKey() (along with their read counterparts) are the functions you want; give them memory BIOs to have them write into a memory buffer.
You can create a memory BIO by invoking e.g.
BIO * b = BIO_new(BIO_s_mem());
and get the memory buffer by invoking
void * buf;
BIO_get_mem_ptr(b, &buf);
You can also create a memory BIO around existing memory by invoking e.g.
BIO * b = BIO_new_mem_buf(buf, 9001)
but the resulting BIO will be read-only.

Resources