I encrypt a message, and I send it to other computer by socket.But I can't decrypt the ciphertext. I used same key and iv in two computers. I try to send ciphertext to other computer,and then send back the ciphertext. I can decrypt the ciphertext in same computer. But I want to decrtpt it in other computer.
This is my code.
#include "cooloi_aes.h"
CooloiAES::CooloiAES(std::string aes_key)
{
//key = (unsigned char*)"01234567890123456789012345678901";
key = (unsigned char*)aes_key.c_str();
iv = (unsigned char*)"aabbccddeeffgghh";
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
OPENSSL_config(NULL);
}
CooloiAES::~CooloiAES()
{
}
CooloiAES* CooloiAES::Create(std::string aes_key)
{
auto ret = new CooloiAES(aes_key);
return ret;
}
void CooloiAES::handleErrors(void)
{
ERR_print_errors_fp(stderr);
abort();
}
int CooloiAES::encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key,
unsigned char *iv, unsigned char *ciphertext)
{
EVP_CIPHER_CTX *ctx;
int len;
int ciphertext_len;
// Create and initialise the context
if(!(ctx = EVP_CIPHER_CTX_new()))
handleErrors();
// Initialise the encryption operation. IMPORTANT - ensure you use a key
// and IV size appropriate for your cipher
// In this example we are using 256 bit AES (i.e. a 256 bit key). The
// IV size for *most* modes is the same as the block size. For AES this
// is 128 bits
if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
handleErrors();
// Provide the message to be encrypted, and obtain the encrypted output.
// EVP_EncryptUpdate can be called multiple times if necessary
if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
handleErrors();
ciphertext_len = len;
// Finalise the encryption. Further ciphertext bytes may be written at
// this stage.
//
if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
handleErrors();
ciphertext_len += len;
// Clean up
EVP_CIPHER_CTX_free(ctx);
return ciphertext_len;
}
int CooloiAES::decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,
unsigned char *iv, unsigned char *plaintext)
{
EVP_CIPHER_CTX *ctx;
int len;
int plaintext_len;
// Create and initialise the context */
if(!(ctx = EVP_CIPHER_CTX_new()))
handleErrors();
// Initialise the decryption operation. IMPORTANT - ensure you use a key
// and IV size appropriate for your cipher
// In this example we are using 256 bit AES (i.e. a 256 bit key). The
// IV size for *most* modes is the same as the block size. For AES this
// is 128 bits
if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
handleErrors();
// Provide the message to be decrypted, and obtain the plaintext output.
// EVP_DecryptUpdate can be called multiple times if necessary
if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
handleErrors();
plaintext_len = len;
// Finalise the decryption. Further plaintext bytes may be written at
// this stage.
if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len))
handleErrors();
plaintext_len += len;
// Clean up
EVP_CIPHER_CTX_free(ctx);
return plaintext_len;
}
std::string CooloiAES::aes_encrypt(std::string msg)
{
int MSG_LEN = ((msg.size() / 16) + 1) * 16;
unsigned char* plaintext = (unsigned char*)msg.c_str();
unsigned char ciphertext[MSG_LEN];
unsigned char decryptedtext[MSG_LEN];
unsigned char cipher[MSG_LEN];
int decryptedtext_len,ciphertext_len;
ciphertext_len = encrypt(plaintext,strlen((char*)plaintext),key,iv,ciphertext);
std::string str(ciphertext,ciphertext+ciphertext_len);
return str;
}
std::string CooloiAES::aes_decrypt(std::string msg)
{
int MSG_LEN = msg.size();
//unsigned char* plaintext = (unsigned char*)msg.c_str();
unsigned char ciphertext[MSG_LEN];
unsigned char decryptedtext[MSG_LEN];
unsigned char cipher[MSG_LEN];
int decryptedtext_len,ciphertext_len;
memcpy(cipher,msg.data(),msg.size());
int len = sizeof(cipher);
decryptedtext_len = decrypt(cipher,len,key,iv,decryptedtext);
decryptedtext[decryptedtext_len] = '\0';
std::string dec((char*)decryptedtext);
return dec;
}
Related
Firstly, I just tell you the scenario I just met. I WANT to test the efficiency of the aes-ofb in libtomcrypt with different plaintext sizes such as 64, 128, 256 Byte, etc. TO make my codes more automatic, I just would like to use the PRNG to fill up the plaintext.
secondly, I just show the function that could fill up the plaintext with yarrow prng.
static inline int PRNG(unsigned char buf[], unsigned int len){
/* create the seed for the pseudo-random number generator */
unsigned char buf_seed[4];
int err;
std::random_device rd;
int x = (int) rd();
memcpy(buf_seed, &x, sizeof(x));
/* send the buf_seed into the PRNG in libtomcrypt*/
prng_state prng;
if ((err = yarrow_start(&prng))!= CRYPT_OK){
printf("Start error:%s\n", error_to_string(err));
}
if((err=yarrow_add_entropy(buf_seed, sizeof(buf_seed),&prng))!=CRYPT_OK){
printf("Add_entropy error:%s\n",error_to_string(err));
}
if((err=yarrow_ready(&prng))!=CRYPT_OK){
printf("Ready error:%s\n",error_to_string(err));
}
yarrow_read(buf,len,&prng);
sprng_done(&prng);
return 0;}
In addition, to make my plaintext could be filled up easily, I just use a pointer array to store the address of different with different sizes. THE corresponding codes like following.
char *plaintext[5];
int len_pt(64);
for (int i = 0; i < 5; i++){
std::cout << "the length of the plaintext is " << len_pt << std::endl;
if (i == 4){
len_pt = 768;
}
plaintext[i] = new char[len_pt];
PRNG((unsigned char *)plaintext[i], len_pt);
len_pt *= 2;
}
When I just used this kind of plaintext, my encryption and decryption will apprear erros.
int tom_aes::ofb(char *plaintext, int len_pt){
if (PRNG(this->iv, this->iv_len) != 0){
std::cout << "[ERROR] PRNG failed!" << std::endl;
}
symmetric_OFB ofb;
/* temporary variables */
unsigned char *ciphertext = new unsigned char[len_pt];
unsigned char *deciphertext = new unsigned char[len_pt];
/* ENCRYPT */
if ((err = ofb_start(find_cipher("aes"), this->iv, key, sizeof(key), 0, &ofb)) != CRYPT_OK){
printf("[tom_aes_ofb]ERROR: in %s, %s\n", __func__, error_to_string(err));
return 0;
}
if ((err = ofb_encrypt((unsigned char*)plaintext, ciphertext, len_pt, &ofb)) != CRYPT_OK){
printf("[tom_aes_ofb]ERROR: in %s, %s\n", __func__, error_to_string(err));
return 0;
}
if ((err = ofb_done(&ofb)) != CRYPT_OK){
printf("[tom_aes_ofb]ERROR: in %s, %s\n", __func__, error_to_string(err));
return 0;
}
/* DECRYPT */
if ((err = ofb_start(find_cipher("aes"), this->iv, key, sizeof(key), 0, &ofb)) != CRYPT_OK){
printf("[tom_aes_ofb]ERROR: in %s, %s\n", __func__, error_to_string(err));
return 0;
}
if ((err = ofb_decrypt(ciphertext, deciphertext, len_pt, &ofb)) != CRYPT_OK){
printf("[tom_aes_ofb]ERROR: in %s, %s\n", __func__, error_to_string(err));
return 0;
}
if ((err = ofb_done(&ofb)) != CRYPT_OK){
printf("[tom_aes_ofb]ERROR: in %s, %s\n", __func__, error_to_string(err));
return 0;
}
if (memcmp(deciphertext, plaintext, len_pt) == 0){
printf("\n[tom_aes_ofb]Recovery: OK\n");
}
else{
printf("\n[tom_aes_ofb]Recovery: FAIL\n");
}
delete ciphertext;
delete deciphertext;
return 0;}
I have just tested above codes. When the plaintext is just like:
char plaintext[] = "Hi I am an AES ECB test vector distributed on 4 128-bit blocks!";
The encryption and decryption could execute smooothly. But the plaintext filled up by my prng function will be destroyted. I cannot figure it out. Wish you could give a hand.
Goal: I want to transfer data from kernel driver to user space app real time.
Method: I use mmap to connect kernel buffer_K and user buffer_U. When I change write data to K, the U will be changed also.
Problem: When I changed the buffer_K, use mmcpy(buffer_k, buffer_another, length), the buffer_K changed, but the buffer_U not change, my change frequency is 4ms.
This is my code
In kernel space, if kernel work done, it will trigger a signal to notice user space.
static uint8_t *mmap_buffer;
mmap_buffer = (uint8_t *)kmalloc(ads1299.samp_size * ads1299.buff_size, GFP_KERNEL);
int event()
{
memcpy(mmap_buffer, ads1299.buff_a, ads1299.buff_size * ads1299.samp_size);
SEND_SIGNAL_TO_APP;
}
int ads1299_mmap(struct file *flip, struct vm_area_struct *vma)
{
unsigned long page;
unsigned long start = (unsigned long)vma->vm_start;
unsigned long size = (unsigned long)(vma->vm_end - vma->vm_start);
vma->vm_flags |= VM_IO;
vma->vm_flags |= VM_SHARED;
page = virt_to_phys(mmap_buffer);
if(remap_pfn_range(vma,start,page>>PAGE_SHIFT, size, vma->vm_page_prot))
{
return -1;
}
return 0;
}
This is my user code
unsigned char *buffer= NULL;
buffer = (unsigned char*)malloc(charDataLen*sizeof(unsigned char));
buffer = (unsigned char *)mmap(NULL, getpagesize(), PROT_READ, MAP_SHARED, fd, 0);
if(buffer == MAP_FAILED)
{
printf("mmap error\r\n");
return -1;
}
int signal_handle()
{
usebufer(buffer)
}
Could you tell me some suggestion about my problem. Thanks.
I need to get both /dev/random and /dev/urandom within kernel module.
get_random_bytes API provided to get /dev/urandom.
But there is no API for /dev/random so I tried to ioctl and read file in kernel space.
Here is what I have done.
using RNDGETPOOL ioctl
in include/linux/random.h
RNDGETPOOL is declared
/* Get the contents of the entropy pool. (Superuser only.) */
#define RNDGETPOOL _IOR( 'R', 0x02, int [2] )
but, It won't work so I checked driver/char/random.h noticed RNDGETPOOL is gone!!
static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
{
int size, ent_count;
int __user *p = (int __user *)arg;
int retval;
switch (cmd) {
case RNDGETENTCNT:
/* inherently racy, no point locking */
if (put_user(input_pool.entropy_count, p))
return -EFAULT;
return 0;
case RNDADDTOENTCNT:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (get_user(ent_count, p))
return -EFAULT;
credit_entropy_bits(&input_pool, ent_count);
return 0;
case RNDADDENTROPY:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (get_user(ent_count, p++))
return -EFAULT;
if (ent_count < 0)
return -EINVAL;
if (get_user(size, p++))
return -EFAULT;
retval = write_pool(&input_pool, (const char __user *)p,
size);
if (retval < 0)
return retval;
credit_entropy_bits(&input_pool, ent_count);
return 0;
case RNDZAPENTCNT:
case RNDCLEARPOOL:
/* Clear the entropy pool counters. */
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
rand_initialize();
return 0;
default:
return -EINVAL;
}
}
I searched google and find out ioctl RNDGETPOOL is removed. done!
using random_read function from driver/char/random.c:997
static ssize_t random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
here is my kernel module's function accesses to /dev/random.
static void read_file()
{
struct file *file;
loff_t pos = 0;
//ssize_t wc;
unsigned char buf_ent[21]={0,};
int ent_c;
int i;
ssize_t length = 0;
mm_segment_t old_fs = get_fs();
set_fs(KERNEL_DS);
file = filp_open("/dev/random", O_WRONLY, 0);
file->f_op->unlocked_ioctl(file, RNDGETENTCNT, &ent_c);
if(ent_c < sizeof(char))
{
printk("not enough entropy\n");
}
printk("ent counter : %d\n", ent_c);
//file->f_op->unlocked_ioctl(file, RNDGETPOOL, &ent_st.buf);
length = file->f_op->read(file, buf_ent, ent_c/ 8, &pos);
if(length <0)
{
printk("failed to random_read\n");
}
printk("length : %d\n", length);
printk("ent: ");
for(i=0;i<length; i++)
{
printk("%02x", buf_ent[i]);
}
printk("\n");
filp_close(file,0);
set_fs(old_fs);
}
outputs seems to be random
first try
[1290902.992048] ent_c : 165
[1290902.992060] length : 20
[1290902.992060] ent: d89290f4a5eea8e087a63943ed0129041e80b568
second try
[1290911.493990] ent_c : 33
[1290911.493994] length : 4
[1290911.493994] ent: 7832640a
by the way random_read function argument has __user keyword. Buf buf in code is in kernel space.
Is appropriate using random_read function in kernel space??
The in-kernel interface to get random bytes is get_random_bytes():
static void read_file(void)
{
unsigned char buf_ent[21];
get_random_bytes(buf_ent, 21);
print_hex_dump_bytes("ent: ", DUMP_PREFIX_NONE, buf_ent, 21);
}
#include <iostream>
#include <Windows.h>
#include <string>
using namespace std;
HANDLE hPort = CreateFile("COM2",
GENERIC_WRITE|GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
DCB dcb;
bool writebyte(char*data)
{
DWORD byteswritten;
if (!GetCommState(hPort,&dcb))
{
printf("\nSerial port can't be open\n");
return false;
}
dcb.BaudRate = CBR_9600;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
if (!SetCommState(hPort,&dcb))
return false;
bool retVal = WriteFile(hPort,data,1,&byteswritten,NULL);
return retVal;
}
int ReadByte()
{
int Val;
BYTE Byte;
DWORD dwBytesTransferred;
DWORD dwCommModemStatus;
if (!GetCommState(hPort,&dcb))
return 0;
SetCommMask(hPort,EV_RXCHAR | EV_ERR);
WaitCommEvent (hPort,&dwCommModemStatus,0);
if (dwCommModemStatus & EV_RXCHAR)
ReadFile (hPort,&Byte,1,&dwBytesTransferred,0);
Val = Byte;
return Val;
}
int main() {
POINT p;
int x;
int y;
int z;
while(0==0){
GetCursorPos(&p);
x = p.x;
y = p.y;
HDC hDC;
hDC = GetDC(NULL);
cin >> z;
cout << GetPixel(hDC, x, y) << endl;
Sleep(z);
ReleaseDC(NULL, hDC);
char data = GetPixel(hDC, x, y);
if (writebyte(&data))
cout <<" DATA SENT.. " << (int)data<< "\n";
}
}
in the part of sending data through serial communication, instead of sending the data as GetPixel(hDC, x, y), it only sends the value "-1" . I was thinking it is because char is only for small integers and the output I was giving is a very very long number. I tried to change it to long int but i still get the same result. That it only sends "-1". I thought that the solution might be converting char to long int or long int to char before sending the data but I don't know how..can someone help me?
Why do you use hDC after releasing it?
ReleaseDC(NULL, hDC);
char data = GetPixel(hDC, x, y);
GetPixel will return -1 (CLR_INVALID) in case of an error (see MSDN).
And, by the way, a COLORREF is not a char, so you lose Information when storing the return value of GetPixel in char data. You should store the complete COLORREF and send/receive all of it's bytes (so send/receive sizeof(COLORREF) bytes).
Also be aware of byte order. If you are transferring multi byte data between two machines then you must assure that both agree on the order of the bytes. If for example one machine is little endian and the other big endian, then they store COLORREF with different byte order in memory. One is storing the COLORREF 0x00BBGGRR in memory as { 0, 0xbb, 0xgg, 0xrr } whereas the other is storing it as { 0xrr, 0xgg, 0xbb, 0 }. So you need to define a transmit byte order which both sides use independant of their host byte order. If you don't want to invent the wheel new, you can take a look at network byte order and reuse that. Socket API gives you some functions like ntohl and htonl which help you in converting from host byte order to network byte order and vice versa.
I'm working in C on a PC, trying to leverage as little C++ as possible, working with binary data stored in unsigned char format, although other formats are certainly possible if worthwhile. The goal is subtracting two signed integer values (which can be ints, signed ints, longs, signed longs, signed shorts, etc.) in binary without converting to other data formats. The raw data is just prepackaged as unsigned char, though, with the user basically knowing which of the signed integer formats should be used for reading (i.e. we know how many bytes to read at once). Even though data is stored as an unsigned char array, data are meant to be read signed as two's-complement integers.
One common way we're often taught in school is adding the negative. Negation, in turn, is often taught to be performed as flipping bits and adding 1 (0x1), resulting in two additions (perhaps a bad thing?); or, as other posts point out, flipping bits past the first zero starting from the MSB. I'm wondering if there is a more efficient way, that may not be easily described as a pen-and-paper operation, but works because of the way data is stored in bit format. Here are some prototypes I've written, which may not be the most efficient way, but which summarizes my progress so far based on textbook methodology.
The addends are passed by reference in case I have to manually extend them to balance their length. Any and all feedback will be appreciated! Thanks in advance for considering.
void SubtractByte(unsigned char* & a, unsigned int & aBytes,
unsigned char* & b, unsigned int & bBytes,
unsigned char* & diff, unsigned int & nBytes)
{
NegateByte(b, bBytes);
// a - b == a + (-b)
AddByte(a, aBytes, b, bBytes, diff, nBytes);
// Restore b to its original state so input remains intact
NegateByte(b, bBytes);
}
void AddByte(unsigned char* & a, unsigned int & aBytes,
unsigned char* & b, unsigned int & bBytes,
unsigned char* & sum, unsigned int & nBytes)
{
// Ensure that both of our addends have the same length in memory:
BalanceNumBytes(a, aBytes, b, bBytes, nBytes);
bool aSign = !((a[aBytes-1] >> 7) & 0x1);
bool bSign = !((b[bBytes-1] >> 7) & 0x1);
// Add bit-by-bit to keep track of carry bit:
unsigned int nBits = nBytes * BITS_PER_BYTE;
unsigned char carry = 0x0;
unsigned char result = 0x0;
unsigned char a1, b1;
// init sum
for (unsigned int j = 0; j < nBytes; ++j) {
for (unsigned int i = 0; i < BITS_PER_BYTE; ++i) {
a1 = ((a[j] >> i) & 0x1);
b1 = ((b[j] >> i) & 0x1);
AddBit(&a1, &b1, &carry, &result);
SetBit(sum, j, i, result==0x1);
}
}
// MSB and carry determine if we need to extend:
if (((aSign && bSign) && (carry != 0x0 || result != 0x0)) ||
((!aSign && !bSign) && (result == 0x0))) {
++nBytes;
sum = (unsigned char*)realloc(sum, nBytes);
sum[nBytes-1] = (carry == 0x0 ? 0x0 : 0xFF); //init
}
}
void FlipByte (unsigned char* n, unsigned int nBytes)
{
for (unsigned int i = 0; i < nBytes; ++i) {
n[i] = ~n[i];
}
}
void NegateByte (unsigned char* n, unsigned int nBytes)
{
// Flip each bit:
FlipByte(n, nBytes);
unsigned char* one = (unsigned char*)malloc(nBytes);
unsigned char* orig = (unsigned char*)malloc(nBytes);
one[0] = 0x1;
orig[0] = n[0];
for (unsigned int i = 1; i < nBytes; ++i) {
one[i] = 0x0;
orig[i] = n[i];
}
// Add binary representation of 1
AddByte(orig, nBytes, one, nBytes, n, nBytes);
free(one);
free(orig);
}
void AddBit(unsigned char* a, unsigned char* b, unsigned char* c,
unsigned char* result) {
*result = ((*a + *b + *c) & 0x1);
*c = (((*a + *b + *c) >> 1) & 0x1);
}
void SetBit(unsigned char* bytes, unsigned int byte, unsigned int bit,
bool val)
{
// shift desired bit into LSB position, and AND with 00000001
if (val) {
// OR with 00001000
bytes[byte] |= (0x01 << bit);
}
else{ // (!val), meaning we want to set to 0
// AND with 11110111
bytes[byte] &= ~(0x01 << bit);
}
}
void BalanceNumBytes (unsigned char* & a, unsigned int & aBytes,
unsigned char* & b, unsigned int & bBytes,
unsigned int & nBytes)
{
if (aBytes > bBytes) {
nBytes = aBytes;
b = (unsigned char*)realloc(b, nBytes);
bBytes = nBytes;
b[nBytes-1] = ((b[0] >> 7) & 0x1) ? 0xFF : 0x00;
} else if (bBytes > aBytes) {
nBytes = bBytes;
a = (unsigned char*)realloc(a, nBytes);
aBytes = nBytes;
a[nBytes-1] = ((a[0] >> 7) & 0x1) ? 0xFF : 0x00;
} else {
nBytes = aBytes;
}
}
The first thing to notice is that signed vs. unsigned doesn't matter to the generated bit pattern in two's complement. All that changes is the interpretation of the result.
The second thing to notice is that an addition has carried if the result is less than either input when done with unsigned arithmetic.
void AddByte(unsigned char* & a, unsigned int & aBytes,
unsigned char* & b, unsigned int & bBytes,
unsigned char* & sum, unsigned int & nBytes)
{
// Ensure that both of our addends have the same length in memory:
BalanceNumBytes(a, aBytes, b, bBytes, nBytes);
unsigned char carry = 0;
for (int j = 0; j < nbytes; ++j) { // need to reverse the loop for big-endian
result[j] = a[j] + b[j];
unsigned char newcarry = (result[j] < a[j] || (unsigned char)(result[j]+carry) < a[j]);
result[j] += carry;
carry = newcarry;
}
}