How to generate an ECDHE public key with OpenSSL? - c

I'm trying to generate an ECDHE key using OpenSSL 1.0.2a on Windows and have the following sample code:
#include <openssl/crypto.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/ecdh.h>
int main()
{
OpenSSL_add_all_algorithms(); ERR_load_crypto_strings();
EVP_PKEY_CTX* parameters_context = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
EVP_PKEY* cparameters = nullptr;
EVP_PKEY* private_key = nullptr;
if (EVP_PKEY_paramgen_init(parameters_context) != 1) { return 1; }
if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(parameters_context, NID_sect571k1) != 1) { return 1; }
if (EVP_PKEY_paramgen(parameters_context, &cparameters) != 1) { return 1; }
EVP_PKEY_CTX* key_generation_context = EVP_PKEY_CTX_new(cparameters, NULL);
if (!key_generation_context) { return 1; }
if (EVP_PKEY_keygen_init(key_generation_context) != 1) { return 1; }
if (EVP_PKEY_keygen(key_generation_context, &private_key) != 1) { return 1; }
BIO* bio = BIO_new(BIO_s_mem());
PEM_write_bio_PUBKEY(bio, private_key); // <== This is where things go wrong.
ERR_free_strings(); EVP_cleanup(); CRYPTO_cleanup_all_ex_data();
}
I tested the said code on other platforms (OSX and Debian Linux, using gcc) and it seems works fine (no errors reported under valgrind).
When I run it on Windows, it always fails on this line:
PEM_write_bio_PUBKEY(bio, private_key);
And I get this "nice" error screen:
I'm at loss figuring out what is wrong: from the many tutorials and documentation pages I could find, this seems to be the right way of doing things.
Before I spend another day trying to figure out what's wrong, I figured it might smarter to ask the community: is this the right way of generating and writing an ECDHE key as PEM format with OpenSSL ?

It was indeed a bug in OpenSSL.
From the OpenSSL-dev mailing-list:
On Tue, Mar 31, 2015, ****** ******* wrote:
>
if (!combine)
*pval = NULL;
I'd suggest deleting the two lines above. The structure should be
cleared without this and the above line is wrong for non pointer
fields anyway.
Steve.
-- Dr Stephen N. Henson. OpenSSL project core developer. Commercial tech support now available see: http://www.openssl.org
See also this other question for details.

Related

Problem getting full version number for Windows 10 with GetFileVersionInfo and VerQueryValue

I want to get the full version number for Windows, just like CMD does:
I ended up with this MS doc that says:
To obtain the full version number for the operating system, call the
GetFileVersionInfo function on one of the system DLLs, such as
Kernel32.dll, then call VerQueryValue to obtain the
\StringFileInfo\\ProductVersion subblock of the file version
information.
So I tried to use those functions with this code:
#include <Windows.h>
#include <wchar.h>
#pragma comment(lib, "Mincore.lib")
int wmain(int argc, wchar_t* argv[])
{
// GetFileVersionInfoW
LPCWSTR fileName = L"C:\\Windows\\System32\\kernel32.dll";
DWORD fileInfoSize;
fileInfoSize = GetFileVersionInfoSizeW(fileName, NULL);
if (fileInfoSize == 0)
{
fwprintf(stderr, L"\nError code: %u\n", GetLastError());
return;
}
// GetFileVersionInfoW
VOID* pFileVerInfo = malloc(fileInfoSize);
if (pFileVerInfo == NULL)
{
fwprintf(stderr, L"Failed allocating!\n");
return;
}
if (!GetFileVersionInfoW(fileName, 0, fileInfoSize, pFileVerInfo))
{
fwprintf(stderr, L"Error code: %u\n", GetLastError());
free(pFileVerInfo);
return;
}
// VerQueryValueW
LPCWSTR subBlock = L"\\StringFileInfo\\\\ProductVersion";
VS_FIXEDFILEINFO * pFileInfo;
UINT pLen = 0;
if (!VerQueryValueW(pFileVerInfo, subBlock, (LPVOID*)& pFileInfo, &pLen))
{
fwprintf(stderr, L"Error code: %u\n", GetLastError());
return;
}
return 0;
}
However, the VerQueryValueW function fails with code 1813 and I have no idea why. I also have no idea how I can show the full version after calling the function.
Can you help me?
L"\\StringFileInfo\\\\ProductVersion" is not correct. There must be a Language ID in the middle. On my Windows 10 installation, a working string is: L"\\StringFileInfo\\040904B0\\ProductVersion". But maybe this would differ on other systems.
As suggested by Jonathan Potter in comments, you could find the ID by querying \\VarFileInfo\\Translation.
Simpler options to achieve the goal include:
Query VS_FIXEDFILEINFO instead of StringFileInfo
Read the OS version from the Windows API instead of querying a random DLL.

connection gwan with aerospike db in C

Hello.
First I'm sorry for my ita-english.
I want use gwan with aerospike but when run the servlet...problem.
I start with this example.c of aerospike. In file example.c I put gwan.h and this is the output ./gwan:
loading
hello.cs: to use .cs scripts, install C#..
hello.lua: to use .lua scripts, install Lua
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Linking example.c: undefined symbol: g_namespace
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To run G-WAN, you must fix the error(s) or remove this Servlet.
Inside example.c:
#include "gwan.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <aerospike/aerospike.h>
#include <aerospike/aerospike_key.h>
#include <aerospike/aerospike_query.h>
#include <aerospike/as_error.h>
#include <aerospike/as_key.h>
#include <aerospike/as_query.h>
#include <aerospike/as_record.h>
#include <aerospike/as_status.h>
#include <aerospike/as_val.h>
#include "example_utils.h"
const char TEST_INDEX_NAME[] = "test-bin-index";
bool query_cb(const as_val* p_val, void* udata);
void cleanup(aerospike* p_as);
bool insert_records(aerospike* p_as);
int
main(int argc, char* argv[])
{
if (! example_get_opts(argc, argv, EXAMPLE_MULTI_KEY_OPTS)) {
exit(-1);
}
aerospike as;
example_connect_to_aerospike(&as);
example_remove_test_records(&as);
example_remove_index(&as, TEST_INDEX_NAME);
if (! example_create_integer_index(&as, "test-bin", TEST_INDEX_NAME))
{
cleanup(&as);
exit(-1);
}
if (! insert_records(&as)) {
cleanup(&as);
exit(-1);
}
if (! example_read_test_records(&as)) {
cleanup(&as);
exit(-1);
}
as_error err;
as_query query;
as_query_init(&query, g_namespace, g_set);
as_query_where_inita(&query, 1);
as_query_where(&query, "test-bin", as_integer_equals(7));
LOG("executing query: where test-bin = 7");
if (aerospike_query_foreach(&as, &err, NULL, &query, query_cb, NULL)
!= AEROSPIKE_OK) {
LOG("aerospike_query_foreach() returned %d - %s", err.code,
err.message);
as_query_destroy(&query);
cleanup(&as);
exit(-1);
}
LOG("query executed");
as_query_destroy(&query);
cleanup(&as);
LOG("simple query example successfully completed");
return 0;
}
bool
query_cb(const as_val* p_val, void* udata)
{
if (! p_val) {
LOG("query callback returned null - query is complete");
return true;
}
as_record* p_rec = as_record_fromval(p_val);
if (! p_rec) {
LOG("query callback returned non-as_record object");
return true;
}
LOG("query callback returned record:");
example_dump_record(p_rec);
return true;
}
void
cleanup(aerospike* p_as)
{
example_remove_test_records(p_as);
example_remove_index(p_as, TEST_INDEX_NAME);
example_cleanup(p_as);
}
bool
insert_records(aerospike* p_as)
{
set
as_record rec;
as_record_inita(&rec, 1);
for (uint32_t i = 0; i < g_n_keys; i++) {
as_error err;
as_key key;
as_key_init_int64(&key, g_namespace, g_set, (int64_t)i);
as_record_set_int64(&rec, "test-bin", (int64_t)i);
if (aerospike_key_put(p_as, &err, NULL, &key, &rec) != AEROSPIKE_OK) {
LOG("aerospike_key_put() returned %d - %s", err.code, err.message);
return false;
}
}
LOG("insert succeeded");
return true;
}
how can connect aerospike with gwan?
Thank you
You need to #pragma link your aerospike library, and make sure all your required header files are in the right place. See G-WAN FAQ or read example code in the G-WAN tarball.
Also, in G-WAN the return code of the main function will be used as HTTP response code, so avoid return -1;.
undefined symbol: g_namespace
the error message is clear. As long as this variable is undefined your C servlet won't compile.
I don't know your library but this variable is probably defined in a library include file - or must be defined by the end user (you). Check the library documentation.
Detailed steps to run Aerospike C-client example with G-WAN,
Download and extract G-WAN server tar on your system
You can start the G-WAN server using ./gwan script present in extracted folder, e.g. ./gwan_linux64-bit/
Get Aerospike C-client from https://github.com/aerospike/aerospike-client-c, and install on your system
Copy example.c to ./gwan_linux64-bit/0.0.0.0_8080/#0.0.0.0/csp/
Make following changes to example.c,
Add following #pragma directive,
#pragma include "/home/user/aerospike-client-c/examples/utils/src/include/"
This will help search example_utils.h, which is necessary for all the example scripts in C-client.
Add following #pragma directive,
#pragma link "/home/user/aerospike-client-c/examples/utils/src/main/example_utils.c"
We shall have to link example_utils.c, as it has definitions of all util functions used in example scripts.
Make changes to the return values. Retun proper HTTP error codes.
Now, you are good to go. Run ./gwan server and access your webservice through browser, http://127.0.0.1:8080/?example.c

PEM_write_PrivateKey() function is not storing the RSA private key in private.pem file

This is the code i am using by taking reference of stack overflow questions asked by other users from here. But when i am trying to use PEM_write_PrivateKey() function to write the private keys into the file. It is not doing it. The console screen get closed automatically after this function call. And the private.pem file doesn't contains anything.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/bio.h>
#include <openssl/pem.h>
#include <openssl/objects.h>
#include <openssl/err.h>
#include <openssl/x509.h>
int main()
{
//
// Local variables definition
//
EVP_PKEY_CTX *evp_ctx = NULL;
EVP_PKEY *ppkey = NULL;
FILE *fpPri = NULL;
FILE *fpPub = NULL;
int retValue = 1;
for (;;)
{
//
// Function allocates public key algorithm context using the algorithm
// specified by id
//
evp_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
if (NULL == evp_ctx)
{
printf("RSA Public key algorithm context is not allocated\n");
break;
} // if
printf("RSA Public key algoritm context allocated\n");
//
// Function initializes a public key algorithm context using key pkey
// for a key genration operation
//
retValue = EVP_PKEY_keygen_init(evp_ctx);
if (1 != retValue)
{
printf("Initialization of public key alogorithm context failed\n");
break;
} // if
printf("Public key alogorithm context initialized\n");
//
// Setting RSA key bit to 2048
//
retValue = EVP_PKEY_CTX_set_rsa_keygen_bits(evp_ctx, 2048);
if (1 != retValue)
{
printf("RSA key bits not set to 2048\n");
break;
} // if
printf("RSA key bits set to 2048\n");
//
// Function performs a key generation operation
//
retValue = EVP_PKEY_keygen(evp_ctx, &ppkey);
if (1 != retValue)
{
printf("Key generation operation failed\n");
break;
} // if
printf("Key generated successfully\n");
//
// Creating a file to store RSA private key
//
fpPri = fopen("./private.pem", "w+");
if (NULL == fpPri)
{
printf("File pointer of private.pem file is not opened\n");
break;
} // if
printf("File pointer or private.pem file opened\n");
retValue = PEM_write_PrivateKey(fpPri, ppkey, NULL, NULL, 0, 0, NULL);
if (1 != retValue)
{
printf("Private key is not written to file private.pem\n");
break;
} // if
printf("Private key written to file private.pem\n");
//
// Final break statement
//
break;
} // for
//
// Releasing all the memory allocations and the handles
//
getchar();
return 0;
}
I'm not exactly sure this is related to your issue but I encountered a similar problem and ended up on this page while trying to figure out what the problem could be. So I thought I'd share my findings hoping it will help someone. I also saw on some other forums that people ran into the same issue I encountered.
The issue: The application exits without any error code when calling PEM_write_PrivateKey on an application compiled using Visual Studio 2015. The same application and code works fine when compiled with VS2010.
I first discovered that Microsoft did some breaking changes to the FILE handle in VS2015.
FILE Encapsulation In previous versions, the FILE type was completely
defined in , so it was possible for user code to reach into a
FILE and modify its internals. The stdio library has been changed to
hide implementation details. As part of this, FILE as defined in
is now an opaque type and its members are inaccessible from
outside of the CRT itself.
https://msdn.microsoft.com/en-us/library/bb531344%28v=vs.140%29.aspx?f=255&MSPPError=-2147217396
By debugging in OpenSSL I figured out that the handler "APPLINK_FSETMOD" was set to "unsupported". This led me to read on the AppLink technology implemention in OpenSSL.
This led me to discover that the solution to my problem was to add the following code in my application.
#include "openssl/applink.c"
Important: You must put the include in one of the .exe source file because GetModuleHandle is passed NULL.
use PEM_write_bio_RSAPrivateKey() insted of PEM_write_PrivateKey() for writing private key to a file
BIO* pOut = BIO_new_file( "key.pem", "w");
if (!pOut)
{
return false;
}
/* Write the key to disk. */
if( !PEM_write_bio_RSAPrivateKey( pOut, pRSA, NULL, NULL, 0, NULL, NULL))
{
return false;
}
BIO_free_all( pOut );
/* Open the PEM file for writing the certificate to disk. */
BIO * x509file = BIO_new_file( "cer.pem", "w" );
if (!x509file )
{
return false;
}
if (!PEM_write_bio_X509( x509file, pX509Cert ))
{
return false;
}
BIO_free_all( x509file );
Perhaps it's because you never called SSL_library_init().
Also, your buffered file is probably not getting flushed before the program exits. Before the end of the program you should call:
fflush(fpPri);

How to use rolling log using log4c?

Can someone tell me how I can use the rolling log feature of log4c API library?
There is only documentation on the functions it provides and there are so many.
If anyone has used rolling log with log4c, would be great to see how to configure it and use it.
Add something like this to your .log4crc file:
<rollingpolicy name="myrollingpolicy"
type="sizewin"
maxsize="1024"
maxnum="10"
/>
<appender name="myrollingfileappender"
type="rollingfile"
logdir="."
prefix="myprefix"
layout="dated"
rollingpolicy="myrollingpolicy"
/>
Then you do logging like normal with:
#include <stdio.h>
#include "log4c.h"
int main(int argc, char** argv) {
int rc = 0;
log4c_category_t* mycat = NULL;
if (log4c_init()) {
printf("log4c_init() failed");
rc = 1;
}
else{
mycat = log4c_category_get("log4c.examples.helloworld");
log4c_category_log(mycat, LOG4C_PRIORITY_ERROR, "Hello World!");
/* Explicitly call the log4c cleanup routine */
if ( log4c_fini()){
printf("log4c_fini() failed");
}
}
return 0;
}
This is all available in the examples from the log4c source code
Since this is a 3 month old question, just wondering if the Wikipedia page was tried -- http://en.wikipedia.org/wiki/Log4c#Development_with_Log4C.

Safely remove a USB drive using the Win32 API?

How do I remove a USB drive using the Win32 API? I do a lot of work on embedded systems and on one of these I have to copy my programs on a USB stick and insert it into the target hardware.
Since I mostly work on the console I don't like to use the mouse and click on the small task-bar icon hundred times a day.
I'd love to write a little program to do exactly that so I can put it into my makefiles, but I haven't found any API call that does the same thing.
Any ideas?
You can use the CM_Request_Device_Eject() function as well as some other possibilities.
Consult the following projects and articles:
DevEject: Straightforward.
http://www.withopf.com/tools/deveject/
A useful CodeProject article:
http://www.codeproject.com/KB/system/RemoveDriveByLetter.aspx
It looks like Sync lets you specify -e to eject removable drives. While not a win32 API, you could probably just call sync -e [drive_letter] from your makefile.
Here is a technet article about removable storage media. Look for DismountNtmsMedia.
Here's a solution in Delphi, that I've modified and put into a service for use in a very large enterprise. Go to: link text
Look for "scapi (Setup & Config Manager API)", and download it. There will be a demo program called USBView that will get you on your way. If you have Delphi, this also includes a TUSBDeviceTree component that you can use to gather information about a USB device when.
Regards
#include<SetupAPI.h>
#include <windows.h>
#include<initguid.h>
#include <newdev.h>
#include <Cfgmgr32.h>
#pragma comment(lib, "Cfgmgr32.lib")
#pragma comment(lib, "Setupapi.lib")
#pragma comment(lib, "Newdev.lib")
int RemoveDevice(const GUID *guid, const wchar_t *hwID) {
HDEVINFO m_hDevInfo;
SP_DEVICE_INTERFACE_DATA spdid;
SP_DEVINFO_DATA spdd;
DWORD dwSize;
BYTE Buf[1024];
PSP_DEVICE_INTERFACE_DETAIL_DATA pspdidd =
(PSP_DEVICE_INTERFACE_DETAIL_DATA)Buf;
printf("try to remove device::%ws\n", hwID);
m_hDevInfo = SetupDiGetClassDevs(guid, NULL, NULL, DIGCF_PRESENT| DIGCF_DEVICEINTERFACE);
if (m_hDevInfo == INVALID_HANDLE_VALUE)
{
printf("GetClassDevs Failed!\n");
return 0;
}
spdid.cbSize = sizeof(spdid);
for (int i = 0; SetupDiEnumDeviceInterfaces(m_hDevInfo, NULL, guid, i, &spdid); i++) {
dwSize = 0;
SetupDiGetDeviceInterfaceDetail(m_hDevInfo,
&spdid, NULL, 0, &dwSize, NULL);
if (dwSize != 0 && dwSize <= sizeof(Buf)) {
pspdidd->cbSize = sizeof(*pspdidd); // 5 Bytes!
ZeroMemory((PVOID)&spdd, sizeof(spdd));
spdd.cbSize = sizeof(spdd);
long res =
SetupDiGetDeviceInterfaceDetail(m_hDevInfo, &
spdid, pspdidd,
dwSize, &dwSize,
&spdd);
if (res) {
OLECHAR* guidString;
OLECHAR* guidString2;
StringFromCLSID(&spdd.ClassGuid, &guidString);
StringFromCLSID(&spdid.InterfaceClassGuid, &guidString2);
printf("%d, %ws, %ws, %ws\n", spdd.DevInst, pspdidd->DevicePath, guidString, guidString2);
CoTaskMemFree(guidString);
CoTaskMemFree(guidString2);
if (!memcmp(pspdidd->DevicePath, hwID, 2 * lstrlenW(hwID))) {
DEVINST DevInstParent = 0;
res = CM_Get_Parent(&DevInstParent, spdd.DevInst, 0);
for (long tries = 0; tries < 10; tries++) {
// sometimes we need some tries...
WCHAR VetoNameW[MAX_PATH];
PNP_VETO_TYPE VetoType = PNP_VetoTypeUnknown;
VetoNameW[0] = 0;
res = CM_Request_Device_EjectW(DevInstParent,
&VetoType, VetoNameW, MAX_PATH, 0);
if ((res == CR_SUCCESS &&
VetoType == PNP_VetoTypeUnknown)) {
printf("remove %ws success!\n", pspdidd->DevicePath);
SetupDiDestroyDeviceInfoList(m_hDevInfo);
return 1;
}
Sleep(500); // required to give the next tries a chance!
}
break;
}
}
}
}
printf("Remove Device Failed!\n");
SetupDiDestroyDeviceInfoList(m_hDevInfo);
return 0;
}
int main(){
GUID GUID_DEVINTERFACE_USB_HUB;
CLSIDFromString(L"F18A0E88-C30C-11D0-8815-00A0C906BED8", &GUID_DEVINTERFACE_USB_HUB);
RemoveDevice(&GUID_DEVINTERFACE_USB_HUB, L"\\\\?\\usb#root_hub30");
return 0;
}
refrences:
How to Prepare a USB Drive for Safe Removal
GUID_DEVINTERFACE

Resources