It's possible to print wpa passphrase in hostapd (by editing the code)?
This is the conf of hostapd (we use TKIP) :
wpa=1
#wpa_psk=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
wpa_passphrase=passphrase
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
In the file hostpad/src/ap/wpa_auth.c, we have lots of information about the connection :
SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
{
struct wpa_ptk PTK;
int ok = 0, psk_found = 0;
const u8 *pmk = NULL;
unsigned int pmk_len;
SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk);
sm->EAPOLKeyReceived = FALSE;
sm->update_snonce = FALSE;
/* WPA with IEEE 802.1X: use the derived PMK from EAP
* WPA-PSK: iterate through possible PSKs and select the one matching
* the packet */
for (;;) {
if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) {
pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr,
sm->p2p_dev_addr, pmk);
if (pmk == NULL)
break;
psk_found = 1;
pmk_len = PMK_LEN;
} else {
pmk = sm->PMK;
pmk_len = sm->pmk_len;
}
wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK);
if (wpa_verify_key_mic(sm->wpa_key_mgmt, &PTK,
sm->last_rx_eapol_key,
sm->last_rx_eapol_key_len) == 0) {
ok = 1;
break;
}
if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt))
break;
}
if (!ok) {
wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
"invalid MIC in msg 2/4 of 4-Way Handshake");
if (psk_found)
wpa_auth_psk_failure_report(sm->wpa_auth, sm->addr);
return;
}
#ifdef CONFIG_IEEE80211R
// ....
#endif /* CONFIG_IEEE80211R */
sm->pending_1_of_4_timeout = 0;
eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm);
if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) {
/* PSK may have changed from the previous choice, so update
* state machine data based on whatever PSK was selected here.
*/
os_memcpy(sm->PMK, pmk, PMK_LEN);
sm->pmk_len = PMK_LEN;
}
sm->MICVerified = TRUE;
os_memcpy(&sm->PTK, &PTK, sizeof(PTK));
sm->PTK_valid = TRUE;
}
My knowledge in networks are limited, and I do not understand very well WPA protocol. There is an article interesting on the question here, but the situation is a little bit different because we are in the case of an attack "man in the middle".
Related
I have been trying to continually print the PWM output of pin 3 inside the switch statement condition but it only prints once. Can I continually print it in serial monitor until it meets the second conditon? or use a while loop? or a if else ?
Here is my code I also have a code with a similar function but it uses if else but still it only prints once
void loop() {
// if there's any serial available, read it:
while (Serial.available() > 0) {
int InitVal = Serial.parseInt();
int red = Serial.parseInt();
switch(InitVal) {
case 1:
if (Serial.read() == '\n') {
analogWrite(redPin, red);
Serial.println(red);
Serial.write(red);
}
break;
case 0:
analogWrite(redPin, 0);
Serial.println(0);
Serial.write(0);
break;
}
}
}
I'am planning to inter-phase this with a GUI . A GUI sends ascii to the arduino reads it then sends the output value to the GUI.
Example
1.GUI sends [1,123] : 1 = the trigger point for the switch statement ; 123 = PWM value.
Arduino receives instructions and it prints out the pwm value
GUI receives pwm value and displays it
Revised code: Stuck at the last while loop maybe i could use a threading function in arduino so that the last while loop would be satisfied/dissatisfied?
void loop() {
int InitVal = 0;
// if there's any serial available, read it:
while (Serial.available() > 0) {
int InitVal = Serial.parseInt();
int red = Serial.parseInt();
switch(InitVal) {
case 1:
if (Serial.read() == '\n') {
InitVal = 1;
//analogWrite(redPin, red);
//Serial.println(red);
// Serial.write(red);
}
break;
case 0:
InitVal = 0;
//analogWrite(redPin, 0);
//Serial.println(0);
//Serial.write(0);
break;
}
if (InitVal) /* when enabled, blink leds */ {
delay(20);
while (InitVal == 1) /* loop forever */{
Serial.println(red);
Serial.write(red);
delay(20);
}
}
}
}
I discarded Serial.parseInt() function, removed the switch statments and followed #Arno Bozo advise on serial listening while following this tutorial on http://forum.arduino.cc/index.php?topic=396450.0
I came up with what I want and here is the code
const int redPin = 3;
const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars]; // temporary array for use when parsing
// variables to hold the parsed data
boolean newData = false;
int InitVal = 0; // change to init value or red
int red = 0;
void setup() {
// initialize serial:
Serial.begin(9600);
// make the pins outputs:
pinMode(redPin, OUTPUT);
}
void loop() {
recvWithStartEndMarkers();
if (newData == true) {
strcpy(tempChars, receivedChars);
// this temporary copy is necessary to protect the original data
// because strtok() used in parseData() replaces the commas with \0
parseData();
One();
newData = false;
}
else {
Zero();
}
}
///////////////////// ///////////////////// /////////////////////
void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
while (Serial.available() > 0 && newData == false) {
rc = Serial.read();
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
///////////////////// ///////////////////// /////////////////////
void parseData() { // split the data into its parts
char * strtokIndx; // this is used by strtok() as an index
strtokIndx = strtok(tempChars,","); // get the first part - the string
InitVal = atoi(strtokIndx); // copy it to messageFromPC
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
red = atoi(strtokIndx); // convert this part to an integer
}
///////////////////// ///////////////////// /////////////////////
void One() {
if (InitVal == 0){
delay(20);
Serial.println(0);
delay(20);
}
}
///////////////////// ///////////////////// /////////////////////
void Zero() {
if (InitVal == 1){
delay(20);
Serial.println(red);
delay(20);
}
}
In Summary the code works like this
1.In serial monitor send this <1,123> : 1 = the trigger point for the switch statement ; 123 = PWM value.
Arduino receives instructions and it prints out the pwm value
If you send <0,123> it prints a zero once
I post a refined code here. The architecture may be reused for serial treatment. I have written it as an example for people I meet and who are learning with arduino.
I have made comments and explanation of ways to avoid delay. Here it is used to print current value of pwm every 1s, without stopping with a delay(1000).
#include <Arduino.h>
// with schedule(f,i) , the function f() will be called every i ms
// schedule(f,i) lines are put in loop() function
// f is of type void f(void)
#define schedule(f,i) {static unsigned long l=0;unsigned long c=millis();if((unsigned long)(c-l)>=i){l=c;f();}}
const int ledPin = 13;
void setup() {
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
}
boolean newCommandHasArrived=false, newParsedCommand=false;
String personalSerialBuffer=""; // char[] would be better; but String are so convenient
enum ECommand {ecmdNoPwm=0, ecmdPwm=1, ecmdBad=10 };
ECommand cmd=ecmdNoPwm;
int cmdArg=0;
boolean readSerialBuffer(String &personalSerialBuffer);
boolean parseCommand(String &apersonalSerialBuffer, ECommand &acmd, int &acmdArg);
void executeCommand(ECommand acmd, int &acmdArg);
void printCurrentValue() {Serial.println(String("cval:") + cmdArg);}
void loop() {
// transfer serial buffer in personal buffer
newCommandHasArrived = readSerialBuffer(personalSerialBuffer);
if (newCommandHasArrived) {
newCommandHasArrived = false;
newParsedCommand = parseCommand(personalSerialBuffer, cmd, cmdArg);
}
if (newParsedCommand) {
newParsedCommand = false;
executeCommand(cmd, cmdArg);
}
// I print current value every 1000ms
//delay(1000); // you can often use delay without pb, but it is a bad usage
// Here I provide you with a quick way to execute a task every 1000ms
{
const unsigned long delayBetweenExecution=1000;
static unsigned long lastTime=0;
unsigned long current = millis();
// note that C++ says that overflow on unsigned is well defined
// it calculates modulo arithmetic
if ((unsigned long)(millis() - lastTime) >= delayBetweenExecution) {
lastTime = current;
Serial.println(String("cval:") + cmdArg);
}
}
// We can make it shorter thanks to a macro:
// but you have to define a void function(void) that uses only global variable
// because it has no argument :
// void printCurrentValue() {Serial.print(String("cval:") + cmdArg);}
//schedule(printCurrentValue, 1000);
}
boolean readSerialBuffer(String &personalSerialBuffer) {
if (Serial.available() > 0) {
personalSerialBuffer.concat(Serial.readString());
}
// the frame is considered finished, if it ends with \n
if (personalSerialBuffer.endsWith("\n"))
return true;
else
return false;
}
boolean parseCommand(String &apersonalSerialBuffer, ECommand &acmd, int &acmdArg) {
// format [ 1, 123]\n
// I omit [ then I read first int : 1
// Note: I cannot detect if no int is found because it will return 0 that is a valid cmd
int readCmd = apersonalSerialBuffer.substring(1).toInt();
// conversion readCmd to acmd
switch (readCmd) {
case 0:
acmd = ecmdNoPwm; break;
case 1:
acmd = ecmdPwm; break;
default:
Serial.println(String("new command unknown: ") +
apersonalSerialBuffer);
apersonalSerialBuffer = "";
return false;
}
// find beginning of 2nd part, separated by ','
int sepPos = apersonalSerialBuffer.indexOf(',');
// no ',' : indexOf returns -1
if (sepPos == -1) {
Serial.println(String("new command could not be parsed: ") +
apersonalSerialBuffer);
apersonalSerialBuffer = "";
return false;
}
// Note: I cannot detect if no int is found because it will return 0 that is a valid cmd
acmdArg = apersonalSerialBuffer.substring(sepPos+1).toInt();
// All is fine
// I have to reset buffer before leaving
apersonalSerialBuffer = "";
return true;
}
void executeCommand(ECommand acmd, int &acmdArg) {
switch(acmd) {
case ecmdNoPwm:
// I erase acmdArg
acmdArg = 0;
analogWrite(ledPin, acmdArg);
Serial.println("cmd no pwm");
break;
case ecmdPwm:
analogWrite(ledPin, acmdArg);
Serial.print("cmd pwm:"); Serial.println(acmdArg);
break;
default:
analogWrite(ledPin, 0);
Serial.println("Bad cmd");
}
}
I'm trying to see how I can get a loaded module image name from an arbitrary address from the kernel code.
In user mode I would do this:
void* pAddr;
VOID* pBase;
WCHAR buff[MAX_PATH] = {0};
//Get address of some function in some module (just to test it)
pAddr = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "GetCurrentProcess");
//Get module base address
RtlPcToFileHeader(pAddr, &pBase);
//Get module image file name
GetModuleFileNameEx(GetCurrentProcess(), (HMODULE)pBase, buff, SIZEOF(buff));
Is there a way to do the same in kernel mode if I have pAddr that can point to some address in kernel or user space?
EDIT: While waiting for the answer I came up with my own code (using undocumented way of traversing PEB):
#ifdef CALLING_FROM_KERNEL_MODE
//Kernel mode
TEB* pTEB = (TEB*)PsGetCurrentThreadTeb();
#else
//User mode
#if defined(_M_X64)
//64-bit
TEB* pTEB = reinterpret_cast<TEB*>(__readgsqword(reinterpret_cast<DWORD_PTR>(&static_cast<NT_TIB*>(nullptr)->Self)));
#else
//32-bit
TEB* pTEB = reinterpret_cast<TEB*>(__readfsdword(reinterpret_cast<DWORD_PTR>(&static_cast<NT_TIB*>(nullptr)->Self)));
#endif
#endif
PEB* p_PEB = pTEB->ProcessEnvironmentBlock;
PEB_LDR_DATA* pPLD = p_PEB->Ldr;
const WCHAR* pModName = NULL;
LIST_ENTRY* pLE = &pPLD->InMemoryOrderModuleList;
LIST_ENTRY* pLE_Head = pLE;
while(pLE_Head != pLE->Flink)
{
PLDR_DATA_TABLE_ENTRY pLDTE = CONTAINING_RECORD(pLE, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
size_t szcbSizeOfImg = (size_t)pLDTE->Reserved3[1];
if((size_t)pAddr - (size_t)pLDTE->DllBase < szcbSizeOfImg)
{
pModName = pLDTE->FullDllName.Buffer;
break;
}
pLE = pLE->Flink;
}
The problem is that although it works from a user-mode, from a kernel mode PsGetCurrentThreadTeb() seems to return NULL. Does this mean kernel threads do not have a TEB?
this can be done by creating list of all loaded modules via ZwQuerySystemInformation with SystemModuleInformation
void fgt(PVOID *Callers, ULONG Count)
{
NTSTATUS status;
ULONG cb = 0x10000;
do
{
status = STATUS_INSUFFICIENT_RESOURCES;
if (PRTL_PROCESS_MODULES prpm = (PRTL_PROCESS_MODULES)ExAllocatePool(PagedPool, cb))
{
if (0 <= (status = NtQuerySystemInformation(SystemModuleInformation, prpm, cb, &cb)))
{
do
{
PVOID Caller = *Callers++;
if (ULONG NumberOfModules = prpm->NumberOfModules)
{
PRTL_PROCESS_MODULE_INFORMATION Modules = prpm->Modules;
do
{
if ((SIZE_T)Caller - (SIZE_T)Modules->ImageBase < Modules->ImageSize)
{
DbgPrint("%p> %s\n", Caller, Modules->FullPathName);
break;
}
} while (Modules++, --NumberOfModules);
}
} while (--Count);
}
ExFreePool(prpm);
}
} while (status == STATUS_INFO_LENGTH_MISMATCH);
}
I'm trying to setup a device tree source file for the first time on my custom platform. On the board is a NXP PCA9555 gpio expander. I'm attempting to setup node for the device and am a bit confused.
Here is where I'm at with the node in the dts file:
ioexp0: gpio-exp#21 {
compatible = "nxp,pca9555";
reg = <21>;
interrupt-parent = <&gpio>;
interrupts = <8 0>;
gpio-controller;
#gpio-cells = <2>;
/*I don't understand the following two lines*/
interrupt-controller;
#interrupt-cells = <2>;
};
I got to this point by using the armada-388-gp.dts source as a guide.
My confusion is on what code processes the #interrupt-cells property. The bindings documentation is not very helpful at all for this chip as it doesn't say anything regarding interrupt cell interpretation.
Looking at the pca953x_irq_setup function in the source code for the pca9555 driver - I don't see anywhere that the #interrupt-cells property is handled. Is this handled in the linux interrupt handling code? I'm just confused as to how I'm suppose to know the meaning of the two interrupt cells.
pca953x_irq_setup for your convenience:
static int pca953x_irq_setup(struct pca953x_chip *chip,
int irq_base)
{
struct i2c_client *client = chip->client;
int ret, i;
if (client->irq && irq_base != -1
&& (chip->driver_data & PCA_INT)) {
ret = pca953x_read_regs(chip,
chip->regs->input, chip->irq_stat);
if (ret)
return ret;
/*
* There is no way to know which GPIO line generated the
* interrupt. We have to rely on the previous read for
* this purpose.
*/
for (i = 0; i < NBANK(chip); i++)
chip->irq_stat[i] &= chip->reg_direction[i];
mutex_init(&chip->irq_lock);
ret = devm_request_threaded_irq(&client->dev,
client->irq,
NULL,
pca953x_irq_handler,
IRQF_TRIGGER_LOW | IRQF_ONESHOT |
IRQF_SHARED,
dev_name(&client->dev), chip);
if (ret) {
dev_err(&client->dev, "failed to request irq %d\n",
client->irq);
return ret;
}
ret = gpiochip_irqchip_add_nested(&chip->gpio_chip,
&pca953x_irq_chip,
irq_base,
handle_simple_irq,
IRQ_TYPE_NONE);
if (ret) {
dev_err(&client->dev,
"could not connect irqchip to gpiochip\n");
return ret;
}
gpiochip_set_nested_irqchip(&chip->gpio_chip,
&pca953x_irq_chip,
client->irq);
}
return 0;
}
This is my first time working with device tree so I'm hoping it's something obvious that I'm just missing.
After looking at all of the comments I did some additional reading and figured out my answer.
I now understand that I was misinterpreting some properties of the device tree. I was previously under the impression that the driver had to specify how all properties were handled. I now see that linux will actually handle many of the generic properties such as gpios or interrupts (which makes a lot of sense).
The documentation on the actual interrupts binding was very helpful, not the documentation for the device driver.
Here is a bit more of a detailed explanation of how the translation from intspec to IRQ_TYPE* happens:
The function of_irq_parse_one copies the interrupt specifier integers to a struct of_phandle_args here. This arg is then passed to irq_create_of_mapping via a consumer function (e.g. of_irq_get). This function then maps these args to a struct irq_fwspec via of_phandle_args_to_fwspec and passes it's fwspec data to irq_create_fwspec_mapping. These functions are all found in irqdomain.c. At this point the irq will belong to an irq_domain or use the irq_default_domain. As far I can tell - the pca853x driver uses the default domain. This domain is often setup by platform specific code. I found mine by searching for irq_domain_ops on cross reference. A lot of these seem to do simple copying of intspec[1] & IRQ_TYPE_SENSE_MASK to the type variable in irq_create_fwspec_mapping via irq_domain_translate. From here the type is set to the irq's irq_data via irqd_set_trigger_type.
of_irq_parse_one:
/**
* of_irq_parse_one - Resolve an interrupt for a device
* #device: the device whose interrupt is to be resolved
* #index: index of the interrupt to resolve
* #out_irq: structure of_irq filled by this function
*
* This function resolves an interrupt for a node by walking the interrupt tree,
* finding which interrupt controller node it is attached to, and returning the
* interrupt specifier that can be used to retrieve a Linux IRQ number.
*/
int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_args *out_irq)
{
struct device_node *p;
const __be32 *intspec, *tmp, *addr;
u32 intsize, intlen;
int i, res;
pr_debug("of_irq_parse_one: dev=%s, index=%d\n", of_node_full_name(device), index);
/* OldWorld mac stuff is "special", handle out of line */
if (of_irq_workarounds & OF_IMAP_OLDWORLD_MAC)
return of_irq_parse_oldworld(device, index, out_irq);
/* Get the reg property (if any) */
addr = of_get_property(device, "reg", NULL);
/* Try the new-style interrupts-extended first */
res = of_parse_phandle_with_args(device, "interrupts-extended",
"#interrupt-cells", index, out_irq);
if (!res)
return of_irq_parse_raw(addr, out_irq);
/* Get the interrupts property */
intspec = of_get_property(device, "interrupts", &intlen);
if (intspec == NULL)
return -EINVAL;
intlen /= sizeof(*intspec);
pr_debug(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen);
/* Look for the interrupt parent. */
p = of_irq_find_parent(device);
if (p == NULL)
return -EINVAL;
/* Get size of interrupt specifier */
tmp = of_get_property(p, "#interrupt-cells", NULL);
if (tmp == NULL) {
res = -EINVAL;
goto out;
}
intsize = be32_to_cpu(*tmp);
pr_debug(" intsize=%d intlen=%d\n", intsize, intlen);
/* Check index */
if ((index + 1) * intsize > intlen) {
res = -EINVAL;
goto out;
}
/* Copy intspec into irq structure */
intspec += index * intsize;
out_irq->np = p;
out_irq->args_count = intsize;
for (i = 0; i < intsize; i++)
out_irq->args[i] = be32_to_cpup(intspec++);
/* Check if there are any interrupt-map translations to process */
res = of_irq_parse_raw(addr, out_irq);
out:
of_node_put(p);
return res;
}
EXPORT_SYMBOL_GPL(of_irq_parse_one)
irq_create_fwspec_mapping:
unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
{
struct irq_domain *domain;
struct irq_data *irq_data;
irq_hw_number_t hwirq;
unsigned int type = IRQ_TYPE_NONE;
int virq;
if (fwspec->fwnode) {
domain = irq_find_matching_fwspec(fwspec, DOMAIN_BUS_WIRED);
if (!domain)
domain = irq_find_matching_fwspec(fwspec, DOMAIN_BUS_ANY);
} else {
domain = irq_default_domain;
}
if (!domain) {
pr_warn("no irq domain found for %s !\n",
of_node_full_name(to_of_node(fwspec->fwnode)));
return 0;
}
if (irq_domain_translate(domain, fwspec, &hwirq, &type))
return 0;
/*
* WARN if the irqchip returns a type with bits
* outside the sense mask set and clear these bits.
*/
if (WARN_ON(type & ~IRQ_TYPE_SENSE_MASK))
type &= IRQ_TYPE_SENSE_MASK;
/*
* If we've already configured this interrupt,
* don't do it again, or hell will break loose.
*/
virq = irq_find_mapping(domain, hwirq);
if (virq) {
/*
* If the trigger type is not specified or matches the
* current trigger type then we are done so return the
* interrupt number.
*/
if (type == IRQ_TYPE_NONE || type == irq_get_trigger_type(virq))
return virq;
/*
* If the trigger type has not been set yet, then set
* it now and return the interrupt number.
*/
if (irq_get_trigger_type(virq) == IRQ_TYPE_NONE) {
irq_data = irq_get_irq_data(virq);
if (!irq_data)
return 0;
irqd_set_trigger_type(irq_data, type);
return virq;
}
pr_warn("type mismatch, failed to map hwirq-%lu for %s!\n",
hwirq, of_node_full_name(to_of_node(fwspec->fwnode)));
return 0;
}
if (irq_domain_is_hierarchy(domain)) {
virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, fwspec);
if (virq <= 0)
return 0;
} else {
/* Create mapping */
virq = irq_create_mapping(domain, hwirq);
if (!virq)
return virq;
}
irq_data = irq_get_irq_data(virq);
if (!irq_data) {
if (irq_domain_is_hierarchy(domain))
irq_domain_free_irqs(virq, 1);
else
irq_dispose_mapping(virq);
return 0;
}
/* Store trigger type */
irqd_set_trigger_type(irq_data, type);
return virq;
}
EXPORT_SYMBOL_GPL(irq_create_fwspec_mapping);
I've edited the WDK kbfiltr.c callback routine to intercept the Esc key and replace it with 'E'.
It works except that it always replaces it with 2 'E's.
So pressing Esc will output 'ee'.
Here's the code:
{
PKEYBOARD_INPUT_DATA pCur = InputDataStart;
PDEVICE_EXTENSION devExt;
WDFDEVICE hDevice;
hDevice = WdfWdmDeviceGetWdfDeviceHandle(DeviceObject);
devExt = FilterGetData(hDevice);
while (pCur < InputDataEnd)
{
ULONG consumed = 0;
if (pCur->MakeCode == 0x01) {//Esc
pCur->MakeCode = 0x12; //E
}
else{
pCur++;
continue;
}
// indicate one packet at a time
(*(PSERVICE_CALLBACK_ROUTINE)(ULONG_PTR)
devExt->UpperConnectData.ClassService)(
devExt->UpperConnectData.ClassDeviceObject,
pCur,
pCur+1,
&consumed);
pCur++;
}
// tell the caller you consumed everything
*InputDataConsumed = (InputDataEnd-InputDataStart);
(*(PSERVICE_CALLBACK_ROUTINE)(ULONG_PTR) devExt->UpperConnectData.ClassService)(
devExt->UpperConnectData.ClassDeviceObject,
InputDataStart,
InputDataEnd,
InputDataConsumed);
}
Anyone know what I'm doing wrong?
I think this was coding error.
Changing the code as below seems to make it work.
{
PKEYBOARD_INPUT_DATA pCur = InputDataStart;
PDEVICE_EXTENSION devExt;
WDFDEVICE hDevice;
hDevice = WdfWdmDeviceGetWdfDeviceHandle(DeviceObject);
devExt = FilterGetData(hDevice);
while (pCur < InputDataEnd)
{
ULONG consumed = 0;
if (pCur->MakeCode == 0x01) {//Esc
pCur->MakeCode = 0x12; //E
}
// indicate one packet at a time
(*(PSERVICE_CALLBACK_ROUTINE)(ULONG_PTR)
devExt->UpperConnectData.ClassService)(
devExt->UpperConnectData.ClassDeviceObject,
pCur,
pCur+1,
&consumed);
pCur++;
}
// tell the caller you consumed everything
*InputDataConsumed = (InputDataEnd-InputDataStart);
}
I have a server which would listen on HTTPS using OpenSSL. For this, I have to provide the certificate to use. However, the current implementation uses a filename to be provided to the OpenSSL API.
I want the certificate information to be read from memory, so that I don't have to ship the certificate file opening. I tried to google, but I didn't come up with any options.
Is is possible? If so, how do I read certificate files from memory instead of a file using OpenSSL?
EDIT: The following was moved from the comments to the question.
// CURRENT
void start_server()
{
const char *fileName = "cert_and_key.pem";
set_server_ssl_file(fileName);
}
set_server_ssl_file(const char *fileName)
{
//initialize context
SSL_CTX_use_certificate_file(CTX, pem, SSL_FILETYPE_PEM);
SSL_CTX_use_PrivateKey_file(CTX, pem, SSL_FILETYPE_PEM);
}
//REQUIRED
void start_server()
{
const char *cert = "--BEGIN CERTIFICATE--............";
const char *key = "--BEGIN RSA PRIVATE KEY--.......";
set_server_ssl_options(cert, key);
}
set_server_ssl_options(const char *cert, const char *key)
{
//IMPLEMENTATION REQUIRED
}
The following code did the job for me:
SSL_CTX *CTX;
X509 *cert = NULL;
RSA *rsa = NULL;
BIO *cbio, *kbio;
const char *cert_buffer = "";
const char *key_buffer = "";
cbio = BIO_new_mem_buf((void*)cert_buffer, -1);
cert = PEM_read_bio_X509(cbio, NULL, 0, NULL);
assert(cert != NULL);
SSL_CTX_use_certificate(CTX, cert);
kbio = BIO_new_mem_buf((void*)key_buffer, -1);
rsa = PEM_read_bio_RSAPrivateKey(kbio, NULL, 0, NULL);
assert(rsa != NULL);
SSL_CTX_use_RSAPrivateKey(CTX, rsa);
The other snippets will only load one certificate. The content of files like http://curl.haxx.se/ca/cacert.pem that contain a lot of different certificates need a new approach. This is adapted from openssl 1.0.1p (mostly openssl-1.0.1p\crypto\x509\by_file.c, char* buf contains the content of a *.pem file, ctx is a boost::asio::ssl::context), add error handling on your own:
BIO *cbio = BIO_new_mem_buf((void*)buf, (int)length);
X509_STORE *cts = SSL_CTX_get_cert_store(ctx.native_handle());
if(!cts || !cbio)
return false;
X509_INFO *itmp;
int i, count = 0, type = X509_FILETYPE_PEM;
STACK_OF(X509_INFO) *inf = PEM_X509_INFO_read_bio(cbio, NULL, NULL, NULL);
if (!inf)
{
BIO_free(cbio);//cleanup
return false;
}
//itterate over all entries from the pem file, add them to the x509_store one by one
for (i = 0; i < sk_X509_INFO_num(inf); i++) {
itmp = sk_X509_INFO_value(inf, i);
if (itmp->x509) {
X509_STORE_add_cert(cts, itmp->x509);
count++;
}
if (itmp->crl) {
X509_STORE_add_crl(cts, itmp->crl);
count++;
}
}
sk_X509_INFO_pop_free(inf, X509_INFO_free); //cleanup
BIO_free(cbio);//cleanup
unsigned char *cert_data = (....);
int cert_len = (....);
X509 *cert = d2i_X509(NULL, &cert_data, cert_len);
SSL_CTX_use_certificate(ctx, cert);
unsigned char *pkey_data = /* ... */;
int pkey_len = /* ... */;
RSA *pkey = d2i_RSAPrivateKey(NULL, &pkey_data, pkey_len);
SSL_CTX_use_RSAPrivateKey(ctx, pkey);
Don't forget & before cert_data and pkey_data - and note that OpenSSL modifies these pointers.
There is another response that uses X509_STORE_add_cert, which is up-voted but incorrect. That answer is a way to do SSL_CTX_load_verify_locations in memory, but does not load the server certificate chain. Replies to that comment also indicate that it does not work.
The following code is a load-from-memory implementation of SSL_CTX_use_certificate_chain_file based on the implementation of that function in OpenSSL:
bool load_cert_chain_from_shared_mem(SSL_CTX *context, const char *cert_buffer)
{
BIO *cbio = BIO_new_mem_buf((void*)cert_buffer, -1);
if (!cbio)
return false;
X509_INFO *itmp;
int i, count = 0, type = X509_FILETYPE_PEM;
STACK_OF(X509_INFO) *inf = PEM_X509_INFO_read_bio(cbio, NULL, NULL, NULL);
if (!inf)
{
BIO_free(cbio);
return false;
}
/* Iterate over contents of the PEM buffer, and add certs. */
BOOL first = TRUE;
for (i = 0; i < sk_X509_INFO_num(inf); i++) {
itmp = sk_X509_INFO_value(inf, i);
if (itmp->x509)
{
/* First cert is server cert. Remaining, if any, are intermediate certs. */
if (first)
{
first = FALSE;
/*
* Set server certificate. Note that this operation increments the
* reference count, which means that it is okay for cleanup to free it.
*/
if (!SSL_CTX_use_certificate(context, itmp->x509))
goto Error;
if (ERR_peek_error() != 0)
goto Error;
/* Get ready to store intermediate certs, if any. */
SSL_CTX_clear_chain_certs(context);
}
else
{
/* Add intermediate cert to chain. */
if (!SSL_CTX_add0_chain_cert(context, itmp->x509))
goto Error;
/*
* Above function doesn't increment cert reference count. NULL the info
* reference to it in order to prevent it from being freed during cleanup.
*/
itmp->x509 = NULL;
}
}
}
sk_X509_INFO_pop_free(inf, X509_INFO_free);
BIO_free(cbio);
return true;
Error:
sk_X509_INFO_pop_free(inf, X509_INFO_free);
BIO_free(cbio);
return false;
}