The situation is that I programmed an assembler and I'm using a std::unordered_multimap container to store all the different instructions, where the actual mnemonic is my key into the map and the associated value is a custom structure with some additonal information about the parameters, etc.
Since I don't need to make any changes to this lookup during runtime I thought I'd declare it as static and const and put all the values manually in an initializer_list.
Altogether it looks like this:
typedef std::wstring STRING;
static const
std::unordered_multimap<STRING, ASM_INSTRUCTION> InstructionLookup = {
// { MNEMONIC, { Opcode1, Opcode2, Param1Type, Param2Type, Param3Type, NrBytes, Bt1, Bt2, Bt3, Bt4, NoRexW, InvalidIn64Bit, InvalidIn32Bit } },
{ L"AAA",{ ot_none, ot_none, par_noparam, par_noparam, par_noparam, 1, 0x37, 0x00, 0x00, 0x00, false, true, false } },
{ L"AAD",{ ot_none, ot_none, par_noparam, par_noparam, par_noparam, 2, 0xD5, 0x0A, 0x00, 0x00, false, true, false } },
{ L"AAD",{ ot_ib, ot_none, par_imm8, par_noparam, par_noparam, 1, 0xD5, 0x00, 0x00, 0x00, false, true, false } },
{ L"AAM",{ ot_none, ot_none, par_noparam, par_noparam, par_noparam, 2, 0xD4, 0x0A, 0x00, 0x00, false, true, false } },
...
My problem now is that there're a lot of instructions (currently 1,225 of them) implemented.
So when I run a code-analysis with Visual Studio, it tells me that the constructor function exceeds the stack with 98,000/16,384 bytes because the constructor first puts all those entries on the stack it seems, before processing them any further.
My question now is how to initialize all that space directly on the heap, preferably without having to rewrite much of it.
I think emplace is what you are looking for:
InstructionLookup.emplace(std::piecewise_construct, std::forward_as_tuple(L"sXs"), std::forward_as_tuple(ot_none, ot_none, par_noparam, par_noparam, par_noparam, 1, 0x37, 0x00, 0x00, 0x00, false, true, false));
I tried to keep your syntax as much as possible and changed the Boost.Assign implementation version from here to use perfect forwarding:
template <typename T, typename U>
class create_unmap
{
private:
std::unordered_multimap<T, U> m_map;
public:
template <typename ...Args>
create_unmap(Args&&... _Val)
{
m_map.emplace(std::forward<Args>(_Val)...);
}
template <typename ...Args>
create_unmap<T, U>& operator()(Args&&... _Val)
{
m_map.emplace(std::forward<Args>(_Val)...);
return *this;
}
operator std::unordered_multimap<T, U>()
{
return std::move(m_map);
}
};
You can declare your map using this syntax:
static const std::unordered_multimap<STRING, ASM_INSTRUCTION> InstructionLookupt = create_unmap<STRING, ASM_INSTRUCTION>
(std::piecewise_construct, std::forward_as_tuple(L"AAA"), std::forward_as_tuple(ot_none, ot_none, par_noparam, par_noparam, par_noparam, 1, 0x37, 0x00, 0x00, 0x00, false, true, false))
(std::piecewise_construct, std::forward_as_tuple(L"AAD"), std::forward_as_tuple(ot_none, ot_none, par_noparam, par_noparam, par_noparam, 1, 0x37, 0x00, 0x00, 0x00, false, true, false))
(std::piecewise_construct, std::forward_as_tuple(L"AAD"), std::forward_as_tuple(ot_none, ot_none, par_noparam, par_noparam, par_noparam, 1, 0x37, 0x00, 0x00, 0x00, false, true, false));
Related
I would like to use webassembly directly from my embedded v8 without the detour via JavaScript. I used the provided hello-world example and the WasmModuleObjectBuilderStreaming class from v8.h. However, I am stuck at how to extract the add function. Help would be appreciated.
#include <include/v8.h>
#include <include/libplatform/libplatform.h>
#include <stdlib.h>
#include <unistd.h>
using v8::HandleScope;
using v8::Isolate;
using v8::Local;
using v8::Promise;
using v8::WasmModuleObjectBuilderStreaming;
int main(int argc, char* argv[]) {
v8::V8::InitializeICUDefaultLocation(argv[0]);
v8::V8::InitializeExternalStartupData(argv[0]);
std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(platform.get());
v8::V8::Initialize();
Isolate::CreateParams create_params;
create_params.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
Isolate* isolate = Isolate::New(create_params);
Isolate::Scope isolate_scope(isolate);
HandleScope scope(isolate);
WasmModuleObjectBuilderStreaming stream(isolate);
// Use the v8 API to generate a WebAssembly module.
//
// |bytes| contains the binary format for the following module:
//
// (func (export "add") (param i32 i32) (result i32)
// get_local 0
// get_local 1
// i32.add)
//
// taken from: https://github.com/v8/v8/blob/master/samples/hello-world.cc#L66
std::vector<uint8_t> wasmbin {
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0x01,
0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07,
0x07, 0x01, 0x03, 0x61, 0x64, 0x64, 0x00, 0x00, 0x0a, 0x09, 0x01,
0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b
};
// write bytes and finish
stream.OnBytesReceived(wasmbin.data(), wasmbin.size());
stream.Finish();
Local<Promise> promise = stream.GetPromise();
// TODO: Get exports, extract `add` & call `add`
}
Build setup:
Follow the instruction in Run the example from the official Getting started with embedding V8. Save the code to sample/wasm.cc and execute following commands:
$ g++ -I. -O2 -Iinclude samples/wasm.cc -o wasm -lv8_monolith -Lout.gn/x64.release.sample/obj/ -pthread -std=c++17`
$ ./wasm`
Solution:
Thanks #liliscent, I adapted my example accordingly. Because we all like, working code:
#include <include/v8.h>
#include <include/libplatform/libplatform.h>
using v8::HandleScope;
using v8::Isolate;
using v8::Local;
using v8::Promise;
using v8::WasmModuleObjectBuilderStreaming;
using v8::WasmCompiledModule;
using v8::Context;
using v8::Local;
using v8::Value;
using v8::String;
using v8::Object;
using v8::Function;
using v8::Int32;
using args_type = Local<Value>[];
int main(int argc, char* argv[]) {
v8::V8::InitializeICUDefaultLocation(argv[0]);
v8::V8::InitializeExternalStartupData(argv[0]);
std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(platform.get());
v8::V8::Initialize();
Isolate::CreateParams create_params;
create_params.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
Isolate* isolate = Isolate::New(create_params);
Isolate::Scope isolate_scope(isolate);
HandleScope scope(isolate);
Local<Context> context = Context::New(isolate);
Context::Scope context_scope(context);
WasmModuleObjectBuilderStreaming stream(isolate);
// Use the v8 API to generate a WebAssembly module.
//
// |bytes| contains the binary format for the following module: //
// (func (export "add") (param i32 i32) (result i32)
// get_local 0
// get_local 1
// i32.add)
//
// taken from: https://github.com/v8/v8/blob/master/samples/hello-world.cc#L66
std::vector<uint8_t> wasmbin {
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0x01,
0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07,
0x07, 0x01, 0x03, 0x61, 0x64, 0x64, 0x00, 0x00, 0x0a, 0x09, 0x01,
0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b
};
// same as calling:
// let module = new WebAssembly.Module(bytes);
Local<WasmCompiledModule> module = WasmCompiledModule::DeserializeOrCompile(isolate,
WasmCompiledModule::BufferReference(0, 0),
WasmCompiledModule::BufferReference(wasmbin.data(), wasmbin.size())
).ToLocalChecked();
// same as calling:
// let module_instance_exports = new WebAssembly.Instance(module).exports;
args_type instance_args{module};
Local<Object> module_instance_exports = context->Global()
->Get(context, String::NewFromUtf8(isolate, "WebAssembly"))
.ToLocalChecked().As<Object>()
->Get(context, String::NewFromUtf8(isolate, "Instance"))
.ToLocalChecked().As<Object>()
->CallAsConstructor(context, 1, instance_args)
.ToLocalChecked().As<Object>()
->Get(context, String::NewFromUtf8(isolate, "exports"))
.ToLocalChecked().As<Object>()
;
// same as calling:
// module_instance_exports.add(77, 88)
args_type add_args{Int32::New(isolate, 77), Int32::New(isolate, 88)};
Local<Int32> adder_res = module_instance_exports
->Get(context, String::NewFromUtf8(isolate, "add"))
.ToLocalChecked().As<Function>()
->Call(context, context->Global(), 2, add_args)
.ToLocalChecked().As<Int32>();
printf("77 + 88 = %d\n", adder_res->Value());
return 0;
}
You can construct a WebAssembly module directly from C++ via v8::WasmCompiledModule class (it will be renamed to v8::WasmModuleObject in next version):
Local<WasmCompiledModule> module = WasmCompiledModule::DeserializeOrCompile(isolate,
WasmCompiledModule::BufferReference(0, 0),
WasmCompiledModule::BufferReference(wasmbin.data(), wasmbin.size())
).ToLocalChecked();
But AFAIK, v8 doesn't expose its webassembly api directly, you have to get them from JS global context. The following code creates a module instance, and gets the exports of the instance:
using args_type = Local<Value>[];
Local<Object> module_instance_exports = context->Global()
->Get(context, String::NewFromUtf8(isolate, "WebAssembly"))
.ToLocalChecked().As<Object>()
->Get(context, String::NewFromUtf8(isolate, "Instance"))
.ToLocalChecked().As<Object>()
->CallAsConstructor(context, 1, args_type{module})
.ToLocalChecked().As<Object>()
->Get(context, String::NewFromUtf8(isolate, "exports"))
.ToLocalChecked().As<Object>()
;
Then you can get the add function from exports object and call it:
Local<Int32> adder_res = module_instance_exports
->Get(context, String::NewFromUtf8(isolate, "add"))
.ToLocalChecked().As<Function>()
->Call(context, context->Global(), 2, args_type{Int32::New(isolate, 77), Int32::New(isolate, 88)})
.ToLocalChecked().As<Int32>();
std::cout << "77 + 88 = " << adder_res->Value() << "\n";
You might be interested in the Wasm C/C++ API proposal, which allows using a Wasm engine directly from C/C++. The design of this API is independent of any particular engine, but the proposal contains a more or less complete prototype implementation on top of V8.
Sample snippet (see e.g. hello.cc):
// ...
auto engine = wasm::Engine::make();
auto store = wasm::Store::make(engine.get());
auto module = wasm::Module::make(store.get(), binary);
auto instance = wasm::Instance::make(store.get(), module.get(), imports);
auto exports = instance->exports();
exports[0]->func()->call();
I use for my Arduino project OneWire library and Dallas one. This one defines an DeviceAddress type which can contains an OneWire device address. I would like to create an array to store my devices address and therefore be able to loop on them.
Following does not compile
DeviceAddress waterTempSensorAddress = { 0x28, 0xCA, 0x98, 0xCF, 0x05, 0x0, 0x0, 0x51 };
DeviceAddress heatWaterSystemTemSensorAddress = { 0x28, 0xC4, 0xA8, 0xCF, 0x05, 0x0, 0x0, 0xC6 };
DeviceAddress test[] = { waterTempSensorAddress, heatWaterSystemTemSensorAddress };
The error is :
pool_manager:62: error: array must be initialized with a brace-enclosed initializer
DeviceAddress test[] = { waterTempSensorAddress, heatWaterSystemTemSensorAddress };
^
Is it possible to declare an Arduino-like array for this? Should I consider using another structure?
Thanks,
It's not really custom type, it's just typedef uint8_t DeviceAddress[8]; and arrays can't be copy constructed unlike classes.
Basically you have two simple ways to do it:
// #1
DeviceAddress test[] = { { 0x28, 0xCA, 0x98, 0xCF, 0x05, 0x0, 0x0, 0x51 }, { 0x28, 0xC4, 0xA8, 0xCF, 0x05, 0x0, 0x0, 0xC6 } };
// and eventually you can define:
DeviceAddress *waterTempSensorAddress = test;
DeviceAddress *heatWaterSystemTemSensorAddress = test + 1;
But it's not so nice.
Another way is using pointers:
// #2
DeviceAddress waterTempSensorAddress = { 0x28, 0xCA, 0x98, 0xCF, 0x05, 0x0, 0x0, 0x51 };
DeviceAddress heatWaterSystemTemSensorAddress = { 0x28, 0xC4, 0xA8, 0xCF, 0x05, 0x0, 0x0, 0xC6 };
DeviceAddress * test2[] = { &waterTempSensorAddress, &heatWaterSystemTemSensorAddress };
The first one is easier to use, second one is little bit less readable:
void da(DeviceAddress const& addr) { /* .... */ }
void something() {
da(test[0]); // #1
da(*(test2[0])); // #2
da(test2[0][0]); // #2 (it's basically two dimensional array of DeviceAddress)
}
Anyway, it's all about the C++ basics.
Little bit harder way is to use container class.
In my project I read the unique ID from an RFID tag, the result is in the form uint8_t TagRead[4].
The result is compared with a number of predefined tag ID values to establish which tag has been read.
For example:
uint8_t RED1[4] = { 0x73, 0xD5, 0xB7, 0xAC };
uint8_t RED2[4] = { 0x7E, 0x27, 0x49, 0x4E };
uint8_t RED3[4] = { 0x02, 0xFD, 0x06, 0x40 };
uint8_t GREEN1[4] = { 0xAB, 0xEC, 0x68, 0x80 };
uint8_t GREEN2[4] = { 0xEE, 0x20, 0x50, 0x4E };
uint8_t GREEN3[4] = { 0x27, 0x06, 0x40, 0x73 };
if (*((uint32_t *)TagRead) == *((uint32_t *)RED2)) {
// RED2 tag has been read
}
else if (*((uint32_t *)TagRead) == *((uint32_t *)GREEN3)) {
// GREEN3 tag has been read
}
My question relates to being able to assign a type/category to a group of tags so that an action can be performed based on the colour of the tag that has been scanned.
It may be that when a RED tag is scanned we switch on a red LED and when a GREEN tag is scanned we switch on a blue LED.
Because there are approximately 50 tags of each colour, I don't want to to have to list all the tag names in the If statement. Instead, is it possible to assign the colour to the tag?
It would then be possible to do:
If scanned tag is of type RED, do red action.
If scanned tag is of type GREEN do green action.
Thanks for your help.
You can create a structure with id and a color enum:
enum class Color { red, green };
struct Tag
{
uint8_t id[4];
Color color;
};
Tag RED1 = { { 0x73, 0xD5, 0xB7, 0xAC }, Color::red } ;
Tag RED2 = { { 0x7E, 0x27, 0x49, 0x4E }, Color::red } ;
Tag RED3 = { { 0x02, 0xFD, 0x06, 0x40 }, Color::red } ;
Tag GREEN1 = { { 0xAB, 0xEC, 0x68, 0x80 }, Color::green } ;
Tag GREEN2 = { { 0xEE, 0x20, 0x50, 0x4E }, Color::green } ;
Tag GREEN3 = { { 0x27, 0x06, 0x40, 0x73 }, Color::green } ;
void test(Tag tag)
{
if (tag.color == Color::red)
{
//
}
else if (tag.color == Color::green)
{
}
}
First, your comparison is undefined behaviour. The right way to go is with a std::memcmp. You also need to take care of endianness.
In order to attach properties (like color) to your tags, simply define a struct:
struct rfid_tag
{
uint8_t value[4];
enum { ... } color;
};
Once you got a struct, you can enrich it with operator== so you can use std::find() to lookup the appropriate tag in one line:
#include <iostream>
#include <array>
#include <algorithm>
#include <cstring>
struct rfid_tag
{
enum color_type { red = 10, blue = 11 };
std::array<uint8_t, 4> value;
color_type color;
};
bool operator==(std::array<uint8_t, 4> const& tagvalue, rfid_tag const& rhs)
{
return std::memcmp(tagvalue.data(), rhs.value.data(), rhs.value.size()) == 0;
}
bool operator==(rfid_tag const& lhs, std::array<uint8_t, 4> const& tagvalue)
{
return tagvalue == lhs;
}
static const std::array<rfid_tag, 3> known_tags = {
rfid_tag{ { 0x00, 0x01, 0x02, 0x03 }, rfid_tag::red },
rfid_tag{ { 0x10, 0x11, 0x12, 0x13 }, rfid_tag::blue },
rfid_tag{ { 0x20, 0x21, 0x22, 0x23 }, rfid_tag::red }
};
int main()
{
const std::array<uint8_t, 4> tag_to_find{ 0x10, 0x11, 0x12, 0x13 };
std::cout << std::find(begin(known_tags), end(known_tags), tag_to_find)->color << "\n"; // outputs "11" as expected
}
demo
There are multiple ways.
You could write a struct which contains your tag along with your color, like this:
struct ColoredTag
{
uint8_t[4] value;
std::string color;
} typename ColoredTag_t;
ColoredTag_t RED1 = {{ 0x73, 0xD5, 0xB7, 0xAC }, "Red"};
ColoredTag_t RED2 = {{ 0x7E, 0x27, 0x49, 0x4E }, "Red"};
ColoredTag_t RED3 = {{ 0x02, 0xFD, 0x06, 0x40 }, "Red"};
ColoredTag_t GREEN1 = {{ 0xAB, 0xEC, 0x68, 0x80 }, "Green"};
ColoredTag_t GREEN2 = {{ 0xEE, 0x20, 0x50, 0x4E }, "Green"};
ColoredTag_t GREEN3 = {{ 0x27, 0x06, 0x40, 0x73 }, "Green"};
Or, you can use a std::map to assign a color to a tag, like this
std map<uint8_t[4], std::string> tags;
public void fillTags()
{
tags[RED1] = "Red";
tags[RED2] = "Red";
//...
}
std::string getColor(uint8_t tag)
{
return tags[tag];
}
There might be some more solutions for this issue, but these are the ones that came to my mind first.
I stumbled upon a neat trick that I've started using to write binary files into (flash) memory on arduino/esp8266 using a library someone posted to one of the esp8266 forums. I've been trying a number of ways to expand upon it. Most recently I've been minifying and compressing my web content files and compiling them in with sketches on my ESP.
The script he posted first uses the output of the unix command xxd -i to write the binary file into an array of hex. The second part uses a struct to combine the file details with a pointer to the array that you can reference from the code whenever the server gets a uri request that matches an entry in the array.
What I would like to do is create a second array of these things with 'default' tools already pre-compressed so I don't have to go through it every time and/or modify my script that builds the header file any time I create a new server sketch. Basically compress and xxd stuff like jquery.js, bootstrap.css and bootstrap.js (or more often their smaller counterparts like backbone or barekit)
Currently once a file is dumped to hex, for example:
FLASH_ARRAY(uint8_t, __js__simple_js,
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x4b, 0x2b,
0xcd, 0x4b, 0x2e, 0xc9, 0xcc, 0xcf, 0x53, 0xc8, 0xad, 0xf4, 0xcf, 0xf3,
0xc9, 0x4f, 0x4c, 0xd1, 0xd0, 0xac, 0x4e, 0xcc, 0x49, 0x2d, 0x2a, 0xd1,
0x50, 0x0a, 0xc9, 0xc8, 0x2c, 0x56, 0x00, 0xa2, 0xc4, 0x3c, 0x85, 0xfc,
0xbc, 0x1c, 0xa0, 0x94, 0x42, 0x6e, 0x6a, 0x71, 0x71, 0x62, 0x7a, 0xaa,
0x92, 0xa6, 0x75, 0x51, 0x6a, 0x49, 0x69, 0x51, 0x9e, 0x42, 0x49, 0x51,
0x69, 0x6a, 0x2d, 0x00, 0x16, 0xa6, 0x25, 0xe5, 0x43, 0x00, 0x00, 0x00);
The existing code added them all at once along with the struct definition:
struct t_websitefiles {
const char* path;
const char* mime;
const unsigned int len;
const char* enc;
const _FLASH_ARRAY<uint8_t>* content;
} files[] = {
{
.path = "/js/simple.js",
.mime = "application/javascript",
.len = 84,
.enc = "gzip",
.content = &__js__simple_js,
},
{
/* details for file2 ...*/
},
{
/* details for file3 ...*/
}
};
Building an array of the structs representing the various files.
My questions amount to noob questions regarding the language syntax. Can I assume that I can use an identical populated struct in the place of what is inside the curly brackets? For example, if I had a second header file with my regularly used libraries, and jquery was compressed in an array called 'default_files' at position 3, could I use something like &default_files[3] in the place of { /* definitions stuffs */ }. Such as:
struct t_websitefiles {
const char* path;
const char* mime;
const unsigned int len;
const char* enc;
const _FLASH_ARRAY<uint8_t>* content;
} files[] = {
{
.path = "/js/simple.js",
.mime = "application/javascript",
.len = 84,
.enc = "gzip",
.content = &__js__simple_js,
},
&default_files[1],
&default_files[3],
{
.path = "/text/readme.txt",
.mime = "text/text",
.len = 112,
.enc = "",
.content = &__text__readme_txt,
}
};
(I'm guessing based on what I've learned thus far it needs the & in front of it?)
I also assume rather than re-writing the struct definition twice,I could do it as a typedef and then just do:
t_websitefiles files[] = { {/*definitions*/},{ /*stuffs*/ } };
Is that correct? Any help is appreciated. It's hard sometimes to find details on the syntax for specific use cases in documentation covering basics. (I would just try it, but I'm not conveniently in front of a compiler at the moment nor do I have direct access to my codebase but want to work on it later when I might not have direct access to the net)
From what I understand, you want create an array of structs such contains both compound literals and items from another array, all defined in header information.
I don't think this is possible - or at least not in the exact way you suggest. I'll try and provide an alternative though.
Can I assume that I can use an identical populated struct in the place of what is inside the curly brackets?
No - you're mixing your types. 'files' is defined as an array of 'struct t_website'.
The code
struct t_websitefiles files[] = {
...
&default_files[1],
...
}
won't compile as you are mixing your types. files is defined as an array of struct t_websitefile, but &default_files[1] is a pointer. C makes a distinction between pointers and non-pointers. They are seperate types.
The obvious option that I can see to do what you want is to use pointers. This will allow you to define everything in header information.
struct t_websitefiles default_files[] = {
....
}
struct t_websitefiles files[] = {
....
}
// An array of pointers
struct t_websitefiles *files_combined[] = {
&files[0],
&files[1],
&default_files[0],
// Or whatever values you want here
...
}
// Example main, just iterates through the combined list
// of files
int main(int argc, char* argv[]) {
int i;
int files_combined_len = sizeof(files_combined)/sizeof(struct t_websitefiles);
for (i=0; i<files_combined_len; i++) {
printf("File %s\r\n", files_combined[i]->path);
}
return 0;
}
Hope this helps.
I am trying to decrypt something using 128BIT AES Decryption. When i attempt to calling CryptDecrypt i get an Error stating "Invalid Algorithm Specified". I get the same problem when using the library posted here: http://www.codeproject.com/KB/security/WinAES.aspx
What can cause this error?
I am using CryptoAPI along on vista64bit with visual studio 2008. I checked in the registry and the AES library is there...
EDIT
BYTE*& encryptedData /* get data length */
HCRYPTPROV cryptoHandle = NULL;
HCRYPTKEY aesKeyHandle = NULL;
hr = InitWinCrypt(cryptoHandle);
if(FAILED(hr))
{
return hr;
}
AesKeyOffering aesKey = { {PLAINTEXTKEYBLOB, CUR_BLOB_VERSION, 0, CALG_AES_128}, 16, { 0xFF, 0x00, 0xFF, 0x1C, 0x1D, 0x1E, 0x03, 0x04, 0x05, 0x0F, 0x20, 0x21, 0xAD, 0xAF, 0xA4, 0x04 }};
if(CryptImportKey(cryptoHandle, (CONST BYTE*)&aesKey, sizeof(AesKeyOffering), NULL, 0, &aesKeyHandle) == FALSE)
{
// DO error
return HRESULT_FROM_WIN32(GetLastError());
}
if(CryptSetKeyParam(aesKeyHandle, KP_IV, { 0xFF, 0x00, 0xFF, 0x1C, 0x1D, 0x1E, 0x03, 0x04, 0x05, 0x0F, 0x20, 0x21, 0xAD, 0xAF, 0xA4, 0x04 } , 0) == FALSE)
{
return HRESULT_FROM_WIN32(GetLastError());
}
BYTE blah2 = CRYPT_MODE_CBC;
// set block mode
if(CryptSetKeyParam(aesKeyHandle, KP_MODE, &blah2, 0) == FALSE)
{
//
return HRESULT_FROM_WIN32(GetLastError());
}
DWORD lol = dataLength / 16 + 1;
DWORD lol2 = lol * 16;
if(CryptDecrypt(aesKeyHandle, 0, TRUE, 0, encryptedData, &lol2) == FALSE)
{
return HRESULT_FROM_WIN32(GetLastError());
}
InitWinCrypt function
if(!CryptAcquireContextW(&cryptoHandle, NULL, L"Microsoft Enhanced RSA and AES Cryptographic Provider", PROV_RSA_AES, CRYPT_VERIFYCONTEXT))
{
if(!CryptAcquireContextW(&cryptoHandle, NULL, L"Microsoft Enhanced RSA and AES Cryptographic Provider", PROV_RSA_AES, 0))
{
return HRESULT_FROM_WIN32(GetLastError());
}
else
{
return S_OK;
}
}
return S_OK;
AesOffering struct:
struct AesKeyOffering
{
BLOBHEADER m_Header;
DWORD m_KeyLength;
BYTE Key[16];
};
EDIT2
After rebooting my computer, and remvoing the CBC chunk. I am now getting Bad Data Errors. The data decrypts fine in C#. But i need to do this using wincrypt.
Are you passing cryptoHandle by reference to InitWithCrypt? If not, your code
if(!CryptAcquireContextW(&cryptoHandle, ...
would only modify InitWinCrypt's copy of cryptoHandle.
EDIT: Given that it does, try getting rid of the CryptSetKeyParam call which sets CRYPT_MODE_CBC