I am trying to encrypt data using Cipher class . I want to specify the initial vector so I use the following functions :
try {
cipherCBC = Cipher.getInstance(Cipher.ALG_DES_CBC_NOPAD, false);
cipherCBC.init(k, Cipher.MODE_ENCRYPT,INITVECTOR,(short)0,(short)8);
cipherCBC.doFinal(data, (short) 0, (short) data.length, result, (short) 0);
} catch (Exception e) {
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
}
with the byte array INITVECTOR initialised by a 8-byte array.
The problem is that I get always an exception caught when I use the init function.
EXTRA INFO:
The key is build here :
octetsLus = (byte) (apdu.setIncomingAndReceive());
if (octetsLus != 16) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
}
// build host crypto
Util.arrayCopy(buffer, (short)(ISO7816.OFFSET_CDATA+4), message, (short) 0,(short) 4);
Util.arrayCopy(buffer, (short)(ISO7816.OFFSET_CDATA+8), message, (short) 4,(short) 4);
Util.arrayCopy(buffer, (short)(ISO7816.OFFSET_CDATA), message, (short) 8,(short) 4);
Util.arrayCopy(buffer, (short)(ISO7816.OFFSET_CDATA+12), message, (short) 12,(short) 4);
// GENERATE SESSION KEYS
encrypt_DES(ENC_key, message,(byte) 0x01);
Util.arrayCopy(result,(short) 0, ENC_SESS_KEY, (short) 0,(short) 16);
encrypt_DES(MAC_key, message,(byte) 0x01);
Util.arrayCopy(result,(short) 0, MAC_SESS_KEY, (short) 0,(short) 16);
ENC_key = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES3_2KEY, false);
ENC_key.setKey(ENC_SESS_KEY, (short) 0);
MAC_key = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES3_2KEY, false);
MAC_key.setKey(MAC_SESS_KEY, (short) 0);
Util.arrayCopy(buffer, (short)(ISO7816.OFFSET_CDATA), message, (short) 0,(short) 8);
Util.arrayCopy(buffer, (short)(ISO7816.OFFSET_CDATA+8), message, (short) 8,(short) 8);
for(i=0;i<8;i++)
message[(short)(16+i)]=(byte)PADDING[i];
Concerning the initial vector, even if I use the following initialization, I get the same problem :
INITVECTOR =new byte[]{(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00};
On the other hand, when I use the init function which use default initialization parameters the encrypt function works well:
cipherCBC.init(k, Cipher.MODE_ENCRYPT);
Related
I would like to be able to capture the berr-counter values in a shell script. I can view the values with:
ip -det link show can0 which gives:
2: can0: <NOARP,ECHO> mtu 16 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 1000
link/can promiscuity 0
can state STOPPED (berr-counter tx 144 rx 128) restart-ms 100
bitrate 125000 sample-point 0.866
tq 133 prop-seg 6 phase-seg1 6 phase-seg2 2 sjw 1
flexcan: tseg1 4..16 tseg2 2..8 sjw 1..4 brp 1..256 brp-inc 1
clock 30000000
I could just parse this output and capture the tx/rx berr-counter, but I would rather capture these values directly. So, I have been trying find where to access these values. I dug into https://github.com/shemminger/iproute2 's code and found where these values are being printed in ip/iplink_can.c in the function:
static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
There is the code:
if (tb[IFLA_CAN_BERR_COUNTER]) {
struct can_berr_counter *bc =
RTA_DATA(tb[IFLA_CAN_BERR_COUNTER]);
fprintf(f, "(berr-counter tx %d rx %d) ", bc->txerr, bc->rxerr);
}
And at the bottom of the same file there is a struct:
struct link_util can_link_util = {
.id = "can",
.maxattr = IFLA_CAN_MAX,
.parse_opt = can_parse_opt,
.print_opt = can_print_opt,
.print_xstats = can_print_xstats,
.print_help = can_print_help,
};
But I can't find anywhere where can_print_opt, or can_link_util.print_opt are called, and I haven't found any success sifting through all of the struct rtattr in the repo.
I'm not sure where to go from here to get these values other than just grabbing them from the output of ip -det link show can0
Maybe a little bit late, but I was trying the same thing : access CAN interface state and error counters from within a userspace application, without calling ip and parsing output.
As you did, I explored iproute2's code, and then read some documentation about netlink for interacting with network devices. Mainly what you have to do is to send an RTM_GETLINK message to a netlink socket, then parse the response, that is a nested list of netlink attributes.
I found this very interesting starting point : http://iijean.blogspot.com/2010/03/howto-get-list-of-network-interfaces-in.html
In this blog the link to full code is broken, but it's available here : https://gist.github.com/cl4u2/5204374.
Note that instead of doing all this "manually", it is also possible to use libnetlink.
Based on this, I was able to write a test code - quick and dirty - that does what you want. You only need to determine my ifIndex_ variable, which is the integer index of your CAN network interface (can be determined by a SIOCGIFINDEX ioctl on your socketcan socket).
printf("Starting rtnetlink stats reading ...\n");
struct sockaddr_nl local;
struct {
struct nlmsghdr nlh;
struct ifinfomsg ifinfo;
} request;
struct sockaddr_nl kernel;
struct msghdr rtnl_msg;
struct iovec io;
pid_t pid = getpid();
qint64 rtnetlink_socket = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
memset(&local, 0, sizeof(local));
local.nl_family = AF_NETLINK;
local.nl_pid = pid;
local.nl_groups = 0;
if (bind(rtnetlink_socket, (struct sockaddr *) &local, sizeof(local)) < 0) {
printf("Binding failed !\n");
return true;
}
printf("Binding successful.\n");
memset(&rtnl_msg, 0, sizeof(rtnl_msg));
memset(&kernel, 0, sizeof(kernel));
memset(&request, 0, sizeof(request));
kernel.nl_family = AF_NETLINK;
request.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
request.nlh.nlmsg_type = RTM_GETLINK;
request.nlh.nlmsg_flags = NLM_F_REQUEST; // NLM_F_ROOT|NLM_F_MATCH| were originally specified and return all interfaces.
request.nlh.nlmsg_pid = pid;
request.nlh.nlmsg_seq = 1; // Must be monotonically increasing, but we send only one.
// Interface is specified only with index.
request.ifinfo.ifi_family = AF_PACKET;
request.ifinfo.ifi_index = ifIndex_;
request.ifinfo.ifi_change = 0;
io.iov_base = &request;
io.iov_len = request.nlh.nlmsg_len;
rtnl_msg.msg_iov = &io;
rtnl_msg.msg_iovlen = 1;
rtnl_msg.msg_name = &kernel;
rtnl_msg.msg_namelen = sizeof(kernel);
if (sendmsg(rtnetlink_socket, &rtnl_msg, 0) < 0) {
printf("Sendmsg finished with an error.\n");
return true;
}
printf("Sendmsg finished successfully.\n");
// Reply reception
int end = 0;
int replyMaxSize = 8192;
char reply[replyMaxSize];
while (!end) {
int len;
struct nlmsghdr *msg_ptr;
struct msghdr rtnl_reply;
struct iovec io_reply;
memset(&io_reply, 0, sizeof(io_reply));
memset(&rtnl_reply, 0, sizeof(rtnl_reply));
io.iov_base = reply;
io.iov_len = replyMaxSize;
rtnl_reply.msg_iov = &io;
rtnl_reply.msg_iovlen = 1;
rtnl_reply.msg_name = &kernel;
rtnl_reply.msg_namelen = sizeof(kernel);
printf("Waiting for data ...\n");
len = recvmsg(rtnetlink_socket, &rtnl_reply, 0);
printf("Received data with length %d.\n", len);
if (len) {
for (msg_ptr = (struct nlmsghdr *) reply; NLMSG_OK(msg_ptr, len); msg_ptr = NLMSG_NEXT(msg_ptr, len)) {
switch(msg_ptr->nlmsg_type) {
case NLMSG_DONE:
end++;
printf("Received NLMSG_DONE end message.\n");
break;
case RTM_NEWLINK:
printf("Received RTM_NEWLINK message with multipart flag : %d.\n", msg_ptr->nlmsg_flags & NLM_F_MULTI);
if (!(msg_ptr->nlmsg_flags & NLM_F_MULTI)) { end++; }
struct ifinfomsg *iface;
struct rtattr *attribute;
struct rtattr *subAttr;
int msgLen, attrPayloadLen;
iface = (struct ifinfomsg*)NLMSG_DATA(msg_ptr);
msgLen = msg_ptr->nlmsg_len - NLMSG_LENGTH(sizeof(*iface));
for (attribute = IFLA_RTA(iface); RTA_OK(attribute, msgLen); attribute = RTA_NEXT(attribute, msgLen)) {
switch(attribute->rta_type) {
case IFLA_IFNAME:
printf("Interface %d name : %s\n", iface->ifi_index, (char *) RTA_DATA(attribute));
break;
case IFLA_LINKINFO:
attrPayloadLen = RTA_PAYLOAD(attribute);
printf("Found link information. Parsing %d payload bytes ...\n", attrPayloadLen);
for (subAttr = (struct rtattr *)RTA_DATA(attribute); RTA_OK(subAttr, attrPayloadLen); subAttr = RTA_NEXT(subAttr, attrPayloadLen)) {
struct rtattr *subSubAttr;
int subAttrPayloadLen = RTA_PAYLOAD(subAttr);
printf("Found sub-attribute. Type : %d, length : %d.\n", subAttr->rta_type, subAttr->rta_len);
switch (subAttr->rta_type) {
case IFLA_INFO_KIND:
printf("\t Link kind : %s.\n", (char *) RTA_DATA(subAttr));
break;
case IFLA_INFO_DATA:
printf("Found link information data. Parsing %d payload bytes ...\n", RTA_PAYLOAD(subAttr));
for (subSubAttr = (struct rtattr *)RTA_DATA(subAttr); RTA_OK(subSubAttr, subAttrPayloadLen); subSubAttr = RTA_NEXT(subSubAttr, subAttrPayloadLen)) {
printf("Found sub-sub-attribute. Type : %d, length : %d.\n", subSubAttr->rta_type, subSubAttr->rta_len);
switch (subSubAttr->rta_type) {
case IFLA_CAN_STATE:
{
int state = *(int *)RTA_DATA(subSubAttr);
printf("State : %d\n", state);
break;
}
case IFLA_CAN_BERR_COUNTER:
{
struct can_berr_counter *bc = (struct can_berr_counter *)RTA_DATA(subSubAttr);
printf("Error counters : (berr-counter tx %d rx %d)\n", bc->txerr, bc->rxerr);
break;
}
default:
break;
}
}
break;
case IFLA_INFO_XSTATS:
default:
break;
}
}
break;
default:
printf("New attribute. Type : %d, length : %d.\n", attribute->rta_type, attribute->rta_len);
break;
}
}
printf("Finished parsing attributes.\n");
break;
case NLMSG_ERROR:
printf("Could not read link details for interface %d.\n", ifIndex_);
end++;
break;
default:
printf("Received unexpected message ID : %d.\n", msg_ptr->nlmsg_type);
break;
}
printf("Finished parsing message.\n");
}
printf("Finished parsing data.\n");
}
}
close(rtnetlink_socket);
return true;
I'm trying to decrypt a file in memory and this file was encrypted with openssl.
For doing that, i use mmap for loading my encrypted file in memory like that:
void* src = mmap(0, statbuf.st_size,PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
and duplicate it because i don't want to modify my original file
void* dst = mmap(0, statbuf.st_size,PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
memcpy (dst, src, statbuf.st_size);
At this step all is ok but i don't know what to do next.
Initialy for testing purpose, i encrypt my file with the openssl command :
system("openssl enc -aes-256-cbc -salt -in my_encryptedfile -out my_encryptedfile.enc -pass")
and decrypt it with this command:
system("openssl enc -d -aes-256-cbc -in my_encryptedfile.enc -out my_encryptedfile -pass pass:")
But i can't use dst in this case, so i search and discovered EVP Symmetric Encryption and Decryption.
link here
Then i encrypted and decrypted my file with that code github code
I try using Key and IV and the decryption in memory and it seem working but i have a problem that i don't understand. When i dump the buffer of my decripted file, i saw "SPACES/NULS" at the end of the file and i don't figure out why it display that. When i try to execute my binany in memory by calling this function :
func()
i got a segmentation fault
Any clues?
typedef void (*JittedFunc)(void);
void* alloc_writable_memory(void *ptr, size_t size) {
ptr = mmap(0, size,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (ptr == (void*)-1) {
perror("mmap");
return NULL;
}
return ptr;
}
int make_memory_executable(void* m, size_t size) {
if (mprotect(m, size, PROT_READ |PROT_WRITE | PROT_EXEC) == -1) {
perror("mprotect");
return -1;
}
return 0;
}
int do_crypt(char *in, char *out, int do_encrypt, int inlen)
{
/* Allow enough space in output buffer for additional block */
unsigned char outbuf[inlen + EVP_MAX_BLOCK_LENGTH];
int outlen;
EVP_CIPHER_CTX *ctx;
/* Bogus key and IV: we'd normally set these from
* another source.
*/
unsigned char key[] = "0123456789abcdeF";
unsigned char iv[] = "1234567887654321";
//int n;
printf("step1\n");
/* Don't set key or IV right away; we want to check lengths */
ctx = EVP_CIPHER_CTX_new();
printf("step2\n");
EVP_CipherInit_ex(ctx, EVP_aes_128_cbc(), NULL, NULL, NULL,do_encrypt);
printf("step3\n");
OPENSSL_assert(EVP_CIPHER_CTX_key_length(ctx) == 16);
OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) == 16);
/* Now we can set key and IV */
EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, do_encrypt);
printf("step4\n");
if(!EVP_CipherUpdate(ctx, outbuf,&outlen, in, inlen))
{
printf("test 2.1: %d %d\n", inlen, outlen);
printf("step8\n");
/* Error */
EVP_CIPHER_CTX_free(ctx);
return 0;
}
//BIO_dump_fp (stdout, (const char *)outbuf, outlen);
printf(" test 2: %d %d\n", inlen, outlen);
if(!EVP_CipherFinal_ex(ctx, outbuf, &outlen))
{
printf("step11\n");
EVP_CIPHER_CTX_free(ctx);
return 0;
}
//copy the decryted buffer in another memory space
memcpy(out, outbuf, outlen);
printf(" test 3: %d %d\n", inlen, outlen);
//BIO_dump_fp (stdout, (const char *)outbuf, outlen);
printf("step12\n");
//fwrite(outbuf, 1, outlen, out);
printf("step13\n");
EVP_CIPHER_CTX_free(ctx);
return 1;
}
int main()
{
FILE *src, *dst;
char *src_mem, *dst_mem, *dst2_mem = NULL;
struct stat statbuf;
int fd;
src = fopen("hello_encrypted", "rb");
if (!src) {
/* Unable to open file for reading */
fprintf(stderr, "ERROR: fopen error: %s\n", strerror(errno));
return errno;
}
/*get the file des from a file*/
fd = fileno(src);
/* find size of input file */
if (fstat (fd,&statbuf) < 0)
{printf ("fstat error");
return 0;
}
/* go to the location corresponding to the last byte */
if (lseek (fd, statbuf.st_size - 1, SEEK_SET) == -1)
{printf ("lseek error");
return 0;
}
if ((src_mem = mmap (0, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0)) == (caddr_t) -1)
{
printf ("mmap error for input");
return 0;
}
if ((dst_mem = mmap (0, statbuf.st_size, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS , -1, 0)) == (caddr_t) -1)
{
printf ("mmap error for output");
return 0;
}
if ((dst2_mem = mmap (0, statbuf.st_size , PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS , -1, 0)) == (caddr_t) -1)
{
printf ("mmap error for output");
return 0;
}
memcpy(dst_mem, src_mem, statbuf.st_size);
int n;
/* 0 for decrypting or 1 for encrypting*/
n = do_crypt(dst_mem,dst2_mem, 0, statbuf.st_size);
printf("%d\n", n);
make_memory_executable(dst2_mem, statbuf.st_size);
//dump of the decrypt binary
BIO_dump_fp (stdout, (const char *)dst2_mem, statbuf.st_size);
//try to launch the decrypted binary ==> segmentation fault
JittedFunc func = dst2_mem;
func();
fclose(src);
return 0;
}
I would remove from the first mmap the flag PROT_WRITE, because you dont want to modify the original file, I think you can also use PROT_PRIV, but have a look to what says the man of mmap.
On the other hand for decrypt your buffer you can use many libraries (a lot of them based on openssl), I specially like CryptoPP but there are many others. Here is an example of how your code will look like on CryptoPP
try {
// CryptoPP::ECB_Mode< CryptoPP::AES >::Decryption d;
// CrypoPP::CBC_Mode< CryptoPP::AES >::Decryption d;
CrypoPP::CBC_CTS_Mode< CryptoPP::AES >::Decryption d;
// What ever mode is best for you
d.SetKey(key.data(), key.size());
// The StreamTransformationFilter removes
// padding as required.
CryptoPP::StringSource s((const uint8_t*)dst, length_dst, true,
new CryptoPP::StreamTransformationFilter(d,
new CryptoPP::StringSink(recovered)
) // StreamTransformationFilter
); // StringSource
} catch(const CryptoPP::Exception& e) {
std::cout << "ERROR decrypting:" << e.what() << std::endl;
return;
}
I want to use the gstreamer's appsrc element to send an images to the gstreamer's pipeline as video stream. I look on the appsrc example, where are used the time-based streaming format. Where each buffer has the timestamp steps on 0.5 second, and the 'need-data' callback calls every 0.5 second.
But in my case, I do not need this feature, I need to use the gst_app_src_push_buffer() directly when an image becomes ready to send (as I understand).
I use the following initialization code (simplified, pseudocode):
void Foo::initializeGst()
{
// Init gstreamer.
::gst_init(nullptr, nullptr);
// Configure appsrc element.
m_appsrc = ::gst_element_factory_make(
"appsrc", "source");
::g_object_set(G_OBJECT(m_appsrc),
"stream-type", GST_APP_STREAM_TYPE_STREAM,
"is-live", true,
nullptr);
// Configure appsrc caps.
const auto caps = ::gst_caps_new_simple(
"video/x-raw",
"format", G_TYPE_STRING, "BGRA",
"width", G_TYPE_INT, 800,
"height", G_TYPE_INT, 600,
"framerate", GST_TYPE_FRACTION, 0, 1,
nullptr);
::g_object_set(G_OBJECT(m_appsrc),
"caps", caps,
nullptr);
// Configure video convertor element.
const auto conv = ::gst_element_factory_make(
"videoconvert", "conv");
// Configure video encoder element.
const auto videoenc = ::gst_element_factory_make(
"x264enc", "video_encoder");
// Configure payloader element.
const auto payloader = ::gst_element_factory_make(
"rtph264pay", "payloader");
::g_object_set(G_OBJECT(payloader),
"config-interval", 60,
nullptr);
// Configure udpsink element.
const auto udpsink = ::gst_element_factory_make(
"udpsink", "udpsink");
::g_object_set(G_OBJECT(udpsink),
"host", "127.0.0.1",
"port", 50666,
nullptr);
// Build pipeline.
m_pipeline = ::gst_pipeline_new("pipeline");
::gst_bin_add_many(GST_BIN(m_pipeline),
m_appsrc,
conv,
videoenc,
payloader,
udpsink,
nullptr);
const auto result = ::gst_element_link_many(
m_appsrc, conv, videoenc, payloader, udpsink, nullptr);
if (!result) {
qDebug() << "Unable to initialize the GST";
} else {
// Play.
const auto status = ::gst_element_set_state(m_pipeline, GST_STATE_PLAYING);
qDebug() << "Status:" << status;
}
}
And the following buffer-access code (simplified, pseudocode):
void Foo::setImage(const QImage &image)
{
GstBuffer *buffer = gst_buffer_new_and_alloc(m_image.byteCount());
const auto bytesCopied = ::gst_buffer_fill(
buffer, 0, m_image.constBits(), m_image.byteCount());
const auto result = ::gst_app_src_push_buffer(
GST_APP_SRC(m_appsrc), buffer);
qDebug() << "Push result" << result << "for copied bytes"
<< bytesCopied;
}
But, nothing happens, I did not see the video stream, e.g. using the VLC player (with the SDP file), and, after some time, the application crashes.
But, if I use the "need-data" signal, and the GST_FORMAT_TIME option:
::g_object_set(G_OBJECT(appsrc),
"stream-type", 0,
"is-live", TRUE,
"format", GST_FORMAT_TIME,
nullptr);
g_signal_connect(appsrc, "need-data", G_CALLBACK(need_data_cb), nullptr);
static void need_data_cb(GstElement *appsrc, guint unused_size, gpointer user_data)
{
static gboolean white = FALSE;
static GstClockTime timestamp = 0;
const guint size = 800 * 600 * 4;
GstBuffer *buffer = ::gst_buffer_new_allocate(nullptr, size, nullptr);
// This makes the image black/white.
::gst_buffer_memset(buffer, 0, white ? 0xff : 0x0, size);
white = !white;
GST_BUFFER_PTS(buffer) = timestamp;
GST_BUFFER_DURATION(buffer) = ::gst_util_uint64_scale_int (1, GST_SECOND, 20);
timestamp += GST_BUFFER_DURATION(buffer);
GstFlowReturn ret;
::g_signal_emit_by_name(appsrc, "push-buffer", buffer, &ret);
::gst_buffer_unref(buffer);
}
then it works...
I did not understand at all, what I need to change to make it work without the timestamps and the GST_FORMAT_TIME option.
Could someone help me please?
BR,
Denis
Ah.. I'm sorry, I stupid.
It is enougth to setup the GST_FORMAT_TIME:
::g_object_set(G_OBJECT(appsrc),
"stream-type", 0,
"is-live", TRUE,
"format", GST_FORMAT_TIME,
nullptr);
And at the buffer creation just set to buffer pts field a current timestamp value, e.g. using the QElapsedTimer:
void Foo::setImage(const QImage &image)
{
GstBuffer *buffer = gst_buffer_new_and_alloc(m_image.byteCount());
const auto bytesCopied = ::gst_buffer_fill(
buffer, 0, m_image.constBits(), m_image.byteCount());
GST_BUFFER_PTS(buffer) = m_timer.nsecsElapsed();
const auto result = ::gst_app_src_push_buffer(
GST_APP_SRC(m_appsrc), buffer);
qDebug() << "Push result" << result << "for copied bytes"
<< bytesCopied;
}
Now, all works, yeehaa.. :)
I am trying to implement a AEAD sample code for encryption Using GCM encryption. But I always get invalid argument error while setting the key
static int init_aead(void)
{
printk("Starting encryption\n");
struct crypto_aead *tfm = NULL;
struct aead_request *req;
struct tcrypt_result tresult;
struct scatterlist plaintext[1] ;
struct scatterlist ciphertext[1];
struct scatterlist gmactext[1];
unsigned char *plaindata = NULL;
unsigned char *cipherdata = NULL;
unsigned char *gmacdata = NULL;
const u8 *key = kmalloc(16, GFP_KERNEL);
char *algo = "rfc4106(gcm(aes))";
unsigned char *ivp = NULL;
int ret, i, d;
unsigned int iv_len;
unsigned int keylen = 16;
/* Allocating a cipher handle for AEAD */
tfm = crypto_alloc_aead(algo, 0, 0);
init_completion(&tresult.completion);
if(IS_ERR(tfm)) {
pr_err("alg: aead: Failed to load transform for %s: %ld\n", algo,
PTR_ERR(tfm));
return PTR_ERR(tfm);
}
/* Allocating request data structure to be used with AEAD data structure */
req = aead_request_alloc(tfm, GFP_KERNEL);
if(IS_ERR(req)) {
pr_err("Couldn't allocate request handle for %s:\n", algo);
return PTR_ERR(req);
}
/* Allocting a callback function to be used , when the request completes */
aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, aead_work_done,&tresult);
crypto_aead_clear_flags(tfm, ~0);
/* Set key */
get_random_bytes((void*)key, keylen);
if((ret = crypto_aead_setkey(tfm, key, 16) != 0)) {
pr_err("Return value for setkey is %d\n", ret);
pr_info("key could not be set\n");
ret = -EAGAIN;
return ret;
}
/* Set authentication tag length */
if(crypto_aead_setauthsize(tfm, 16)) {
pr_info("Tag size could not be authenticated\n");
ret = -EAGAIN;
return ret;
}
/* Set IV size */
iv_len = crypto_aead_ivsize(tfm);
if (!(iv_len)){
pr_info("IV size could not be authenticated\n");
ret = -EAGAIN;
return ret;
}
plaindata = kmalloc(16, GFP_KERNEL);
cipherdata = kmalloc(16, GFP_KERNEL);
gmacdata = kmalloc(16, GFP_KERNEL);
ivp = kmalloc(iv_len, GFP_KERNEL);
if(!plaindata || !cipherdata || !gmacdata || !ivp) {
printk("Memory not availaible\n");
ret = -ENOMEM;
return ret;
}
for (i = 0, d = 0; i < 16; i++, d++)
plaindata[i] = d;
memset(cipherdata, 0, 16);
memset(gmacdata, 0, 16);
for (i = 0,d=0xa8; i < 16; i++, d++)
ivp[i] = d;
sg_init_one(&plaintext[0], plaindata, 16);
sg_init_one(&ciphertext[0], cipherdata, 16);
sg_init_one(&gmactext[0], gmacdata, 128);
aead_request_set_crypt(req, plaintext, ciphertext, 16, ivp);
aead_request_set_assoc(req, gmactext, 16);
ret = crypto_aead_encrypt(req);
if (ret)
printk("cipher call returns %d \n", ret);
else
printk("Failure \n");
return 0;
}
module_init(init_aead);
module_exit(exit_aead);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("My code for aead encryption test");
}
On inserting the module I get following output
Starting encryption
Return value for setkey is -22
key could not be set
According to AEAD specification aead uses aes-128 for encryption hence the block size should be 128 bit .
But my system shows only 1 Byte block size support for AEAD
name : rfc4106(gcm(aes))
driver : rfc4106-gcm-aesni
module : aesni_intel
priority : 400
refcnt : 1
selftest : passed
type : nivaead
async : yes
blocksize : 1
ivsize : 8
maxauthsize : 16
geniv : seqiv
Does the invalid argument error is thrown becuase of the block size. If so , what shall I do to make it work ?
The block size of AES is indeed always 128 bit. The block size of GCM is a different matter though. GCM (Galois-Counter Mode) is - as the name suggests - build on top of the CTR (Counter) mode of operation, sometimes also called the SIC (Segmented Integer Counter) mode of operation. This turns AES into a stream cipher. Stream ciphers - by definition - have a block size of one byte (or, more precisely, one bit, but bit level operations are usually not supported by API's).
Block size however has little to do with the key size displayed in the call, and the argument does seem to require bytes instead of bits (in which key lengths are usually defined).
The size of the IV should be 12 bytes (the default). Otherwise additional calculations may be needed by the GCM implementation (if those exist at all).
For Aes GCM RFC 4106 the key must be 20 bytes. I don't known yet why. I've looked into ipsec source code to see how the encryption is made there.
I am continuously getting an Access Violation Error with a all my kernels which I am trying to build. Other kernels which I take from books seem to work fine.
https://github.com/ssarangi/VideoCL - This is where the code is.
Something seems to be missing in this. Could someone help me with this.
Thanks so much.
[James] - Thanks for the suggestion and you are right. I am doing it on Win 7 with a AMD Redwood card. I have the Catalyst 11.7 drivers with AMD APP SDK 2.5. I am posting the code below.
#include <iostream>
#include "bmpfuncs.h"
#include "CLManager.h"
void main()
{
float theta = 3.14159f/6.0f;
int W ;
int H ;
const char* inputFile = "input.bmp";
const char* outputFile = "output.bmp";
float* ip = readImage(inputFile, &W, &H);
float *op = new float[W*H];
//We assume that the input image is the array “ip”
//and the angle of rotation is theta
float cos_theta = cos(theta);
float sin_theta = sin(theta);
try
{
CLManager* clMgr = new CLManager();
// Build the Source
unsigned int pgmID = clMgr->buildSource("rotation.cl");
// Create the kernel
cl::Kernel* kernel = clMgr->makeKernel(pgmID, "img_rotate");
// Create the memory Buffers
cl::Buffer* clIp = clMgr->createBuffer(CL_MEM_READ_ONLY, W*H*sizeof(float));
cl::Buffer* clOp = clMgr->createBuffer(CL_MEM_READ_WRITE, W*H*sizeof(float));
// Get the command Queue
cl::CommandQueue* queue = clMgr->getCmdQueue();
queue->enqueueWriteBuffer(*clIp, CL_TRUE, 0, W*H*sizeof(float), ip);
// Set the arguments to the kernel
kernel->setArg(0, clOp);
kernel->setArg(1, clIp);
kernel->setArg(2, W);
kernel->setArg(3, H);
kernel->setArg(4, sin_theta);
kernel->setArg(5, cos_theta);
// Run the kernel on specific NDRange
cl::NDRange globalws(W, H);
queue->enqueueNDRangeKernel(*kernel, cl::NullRange, globalws, cl::NullRange);
queue->enqueueReadBuffer(*clOp, CL_TRUE, 0, W*H*sizeof(float), op);
storeImage(op, outputFile, H, W, inputFile);
}
catch(cl::Error error)
{
std::cout << error.what() << "(" << error.err() << ")" << std::endl;
}
}
I am getting the error at the queue->enqueueNDRangeKernel line.
I have the queue and the kernel stored in a class.
CLManager::CLManager()
: m_programIDs(-1)
{
// Initialize the Platform
cl::Platform::get(&m_platforms);
// Create a Context
cl_context_properties cps[3] = {
CL_CONTEXT_PLATFORM,
(cl_context_properties)(m_platforms[0])(),
0
};
m_context = cl::Context(CL_DEVICE_TYPE_GPU, cps);
// Get a list of devices on this platform
m_devices = m_context.getInfo<CL_CONTEXT_DEVICES>();
cl_int err;
m_queue = new cl::CommandQueue(m_context, m_devices[0], 0, &err);
}
cl::Kernel* CLManager::makeKernel(unsigned int programID, std::string kernelName)
{
cl::CommandQueue queue = cl::CommandQueue(m_context, m_devices[0]);
cl::Kernel* kernel = new cl::Kernel(*(m_programs[programID]), kernelName.c_str());
m_kernels.push_back(kernel);
return kernel;
}
I checked your code. I'm on Linux though. At runtime I'm getting Error -38, which means CL_INVALID_MEM_OBJECT. So I went and checked your buffers.
cl::Buffer* clIp = clMgr->createBuffer(CL_MEM_READ_ONLY, W*H*sizeof(float));
cl::Buffer* clOp = clMgr->createBuffer(CL_MEM_READ_WRITE, W*H*sizeof(float));
Then you pass the buffers as a Pointer:
kernel->setArg(0, clOp);
kernel->setArg(1, clIp);
But setArg is expecting a value, so the buffer pointers should be dereferenced:
kernel->setArg(0, *clOp);
kernel->setArg(1, *clIp);
After those changes the cat rotates ;)