In a kernel level project I want to encrypt a packet using des algorithm , need to use the function
static int des_setkey(void *ctx,const u8 *key,
unsigned int keylen,
u32 *flags)
I want to know how the key to be passed to the function , which value to be used as the to the key , its a pointer type so will be an address value
http://lxr.kelp.or.kr/ident?v=2.6.28;i=des_setkey
* Cryptographic API.
*
* s390 implementation of the DES Cipher Algorithm.
*
* Copyright IBM Corp. 2003,2007
* Author(s): Thomas Spatzier
* Jan Glauber (jan.glauber#de.ibm.com)
typeA A=xy;
functionname(typeA* a, typeA b)
--> functionname(&A,A);
crypto_des_check_key(const u8 *key, unsigned int keylen, u32 *flags)
{
u32 n, w;
n = parity[key[0]]; n <<= 4;
n |= parity[key[1]]; n <<= 4;
n |= parity[key[2]]; n <<= 4;
n |= parity[key[3]]; n <<= 4;
n |= parity[key[4]]; n <<= 4;
n |= parity[key[5]]; n <<= 4;
n |= parity[key[6]]; n <<= 4;
n |= parity[key[7]];
w = 0x88888888L;
if ((*flags & CRYPTO_TFM_REQ_WEAK_KEY)
&& !((n - (w >> 3)) & w)) { /* 1 in
-->CRYPTO_TFM_REQ_WEAK_KEY is a flag
--> source/include/linux/crypto.h
/*
* Transform masks and values (for crt_flags).
*/
#define CRYPTO_TFM_REQ_MASK 0x000fff00
#define CRYPTO_TFM_RES_MASK 0xfff00000
#define CRYPTO_TFM_REQ_WEAK_KEY 0x00000100
#define CRYPTO_TFM_REQ_MAY_SLEEP 0x00000200
#define CRYPTO_TFM_REQ_MAY_BACKLOG 0x00000400
#define CRYPTO_TFM_RES_WEAK_KEY 0x00100000
#define CRYPTO_TFM_RES_BAD_KEY_LEN 0x00200000
#define CRYPTO_TFM_RES_BAD_KEY_SCHED 0x00400000
#define CRYPTO_TFM_RES_BAD_BLOCK_LEN 0x00800000
#define CRYPTO_TFM_RES_BAD_FLAGS 0x01000000
source/arch/s390/crypto/des_s390.c
#define DES_EXPKEY_WORDS 32
typedef unsigned char u8;
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef signed char s8;
typedef short s16;
typedef int s32;
typedef long long s64;
static int des_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags)
{
return setkey(((struct des_ctx *)ctx)->expkey, key, keylen, flags);
}
struct des_ctx {
u32 expkey[DES_EXPKEY_WORDS];
};
This looks like it is from the 2.6.16 (ish) linux kernel. Later kernels have seen the crypto system api re-written slightly.
for this kernel this might help:-
*key is a pointer to a 16 byte array, ( unsigned char[16] ).
*ctx is a pointer to a struct des_ctx structure;
*flags is a pointer to a 32bit unsigned int that will have CRYPTO_TFM_RES_WEAK_KEY set if you have supplied a weak key ( one that fails FIPS 74 - see the ekey() function )
Related
I have some mpeg ts bitfields, for example transport stream package:
struct ts_package_header_s {
unsigned int continuity_counter :4;
unsigned int adaptation_field_control :2;
unsigned int transport_scrambling_control :2;
unsigned int PID :13;
unsigned int transport_priority :1;
unsigned int payload_unit_start_indicator :1;
unsigned int transport_error_indicator :1;
unsigned int sync_byte :8;
};
struct ts_package_s {
struct ts_package_header_s ts_header;
unsigned char ts_body[TS_BODY];
};
union ts_package_u {
struct ts_package_s ts_package;
unsigned char bytes[TS_PACKAGE];
};
In my source code I initialize header struct:
pat_package_header.sync_byte = 0x47;
pat_package_header.transport_error_indicator = 0;
pat_package_header.payload_unit_start_indicator = 1;
pat_package_header.transport_priority = 0;
pat_package_header.PID = PAT_PID;
pat_package_header.transport_scrambling_control = 0;
pat_package_header.adaptation_field_control = 1;
pat_package_header.continuity_counter = 0;
And than I make ts_packag union
union ts_package_u package;
package.ts_package.ts_header = pat_package_header;
Than I fill ts_body array.
When I write this package to file. I get backwards array:
10 00 40 47 XX XX XX.. instead of 47 40 10 00 XX XX XX..
I tried to cast my struct to char* instead of using union, but got same result.
Where is fault? Thanks.
It's dangerous to use try and serialise structs like this directly to disk where the format must be known across different architectures, or use different compilers.
Compilers differ in how they store bitfields and the underlying endianess of your architecture also changes how the data is stored
For example, it could be that a compiler chooses to align bitfields on byte, word or some other boundary. It's a compiler decision. It may also choose to save the bits in any order, which usually depends on the endianess of your machine.
In order to safely write this header to disk, you need to serialise the data yourself. The header is 32-bit and Big Endian according to Wikipedia.
So for example:
#include <stdio.h>
#define TS_BODY 1024
#define PAT_PID 0x40
struct ts_package_header_s {
unsigned int continuity_counter :4;
unsigned int adaptation_field_control :2;
unsigned int transport_scrambling_control :2;
unsigned int PID :13;
unsigned int transport_priority :1;
unsigned int payload_unit_start_indicator :1;
unsigned int transport_error_indicator :1;
unsigned int sync_byte :8;
};
struct ts_package_s {
struct ts_package_header_s ts_header;
unsigned char ts_body[TS_BODY];
};
static void write_ts( struct ts_package_s pat_package )
{
FILE* f = fopen( "test.ts", "wb+" );
unsigned int header = 0;
if( f == NULL )
return;
header = pat_package.ts_header.sync_byte << 24;
header |= ( pat_package.ts_header.transport_error_indicator << 23 );
header |= ( pat_package.ts_header.payload_unit_start_indicator << 22 );
header |= ( pat_package.ts_header.transport_priority << 21 );
header |= ( pat_package.ts_header.PID << 8 );
header |= ( pat_package.ts_header.transport_scrambling_control << 6 );
header |= ( pat_package.ts_header.adaptation_field_control << 4 );
header |= ( pat_package.ts_header.continuity_counter );
/* Write the 32-bit header as big-endian */
unsigned char byte = header >> 24;
fwrite( &byte, 1, 1, f );
byte = ( header >> 16 ) & 0xFF;
fwrite( &byte, 1, 1, f );
byte = ( header >> 8 ) & 0xFF;
fwrite( &byte, 1, 1, f );
byte = header & 0xFF;
fwrite( &byte, 1, 1, f );
fclose( f );
}
int main( int argc, char* argv[] )
{
struct ts_package_s pat_package;
pat_package.ts_header.sync_byte = 0x47;
pat_package.ts_header.transport_error_indicator = 0;
pat_package.ts_header.payload_unit_start_indicator = 1;
pat_package.ts_header.transport_priority = 0;
pat_package.ts_header.PID = PAT_PID;
pat_package.ts_header.transport_scrambling_control = 0;
pat_package.ts_header.adaptation_field_control = 1;
pat_package.ts_header.continuity_counter = 0;
write_ts( pat_package );
return 0;
}
Writes a file with the following header:
0x47 0x40 0x01 0x10
which appears to be correct according to the values you're using.
I tried to create a c code that produce 10 sec of C note. But it seem the output .wav file didn't produce any sound.
I'm still new in C programming and it would be helpful if you can point my mistakes.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
//music note
#define C 261.6256
#define TIME 10
#define POINT 20
#define AMP 10000
#define c 5
//wav file header
typedef struct
{
char ChuckID[4];
unsigned long ChuckSize;
char format[4];
char subChunk1ID[4];
unsigned long SubChunk1Size;
unsigned short AudioFormat;
unsigned short NumChannels;
unsigned long SampleRate;
unsigned long ByteRate;
unsigned short block_allign;
unsigned short bits_per_sample;
char data[4];
unsigned long data_size;
/*char riff_tag[4];
int riff_length;
char wave_tag[4];
char fmt_tag[4];
int fmt_length;
short audio_format;
short num_channels;
int sample_rate;
int byte_rate;
short block_align;
short bits_per_sample;
char data_tag[4];
int data_length;*/
} wavheader;
int main(int argc, char **argv)
{
wavheader wave = {"RIFF",1764036,"WAVE","fmt",16,1,1,44100,176400,4,32,"data",1764000};
float data;
float f = C;
int fs = 44100;
int k;
float *buff;
FILE *out_file = fopen("ongaku.wav","w");
buff = (float*)malloc(sizeof(float)*fs*TIME);
for (k = 0; k<(int)(TIME*fs); k++)
{
data=AMP*sin(2*M_PI*f*k/fs);
//printf("%f\n",data);
}
fwrite(buff,sizeof(float),fs*TIME,out_file);
return 0;
}
I have this working with 8-bit data but unsuccessful with 12/16-bit let alone float data. One thing that's essential, is not to hard code buffer sizes in the header. Other points to watch out for are endian-ness (I happened not to need to adjust), and structure packing (ditto). My use of BPS/8 would also come unstuck when working with 12-bit data.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define FREQ 261.6256 // C
//#define FREQ 440.0 // A
#define M_PI 3.14159265358979323846
#define TIME 10
#define AMP 64.0 // don't use max volume
#define MID 128.0 // 8-bit is range 0..255
//#define MID 0.0 // 16-bit is range -32767.. 32767
#define BPS 8
#define CHANNS 1
#define RATE 44100
//wav file header
typedef struct {
char ChuckID[4];
unsigned long ChuckSize;
char format[4];
char subChunk1ID[4];
unsigned long SubChunk1Size;
unsigned short AudioFormat;
unsigned short NumChannels;
unsigned long SampleRate;
unsigned long ByteRate;
unsigned short block_allign;
unsigned short bits_per_sample;
char data[4];
unsigned long data_size;
} wavheader;
int main(int argc, char **argv)
{
int k, samples = RATE * TIME;
double data;
FILE *out_file;
unsigned char *buff;
wavheader wave = {
"RIFF",
36 + samples * CHANNS * BPS/8,
"WAVE",
"fmt ", // "fmt" was error in OP
16,
1,
CHANNS,
RATE,
RATE * CHANNS * BPS/8,
CHANNS * BPS/8,
BPS,
"data",
samples * CHANNS * BPS/8
};
buff = malloc(BPS/8 * samples);
out_file = fopen("ongaku.wav","w");
fwrite(&wave, sizeof(wave), 1, out_file);
for (k=0; k<samples; k++) {
data = MID + AMP * sin(2 * M_PI * FREQ * TIME * k / (double)samples);
buff[k] = (unsigned char)floor(data+0.5);
}
fwrite(buff, BPS/8, samples, out_file);
fclose (out_file);
free (buff);
return 0;
}
Put some data into buff, I guess your data variable is holding that value. and after that
if everything else is working correctly, use
fflush(out_file);
or use
fclose(out_file);
I am trying to create .bmp file (filled with one colour for testing purposes).
Here is code that I'm using:
#include <stdio.h>
#define BI_RGB 0
typedef unsigned int UINT;
typedef unsigned long DWORD;
typedef long int LONG;
typedef unsigned short WORD;
typedef unsigned char BYTE;
typedef struct tagBITMAPFILEHEADER {
UINT bfType;
DWORD bfSize;
UINT bfReserved1;
UINT bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER {
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER;
typedef struct COLORREF_RGB
{
BYTE cRed;
BYTE cGreen;
BYTE cBlue;
}COLORREF_RGB;
int main(int argc, char const *argv[])
{
BITMAPINFOHEADER bih;
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biWidth = 600;
bih.biHeight = 600;
bih.biSizeImage = bih.biWidth * bih.biHeight * 3;
bih.biPlanes = 1;
bih.biBitCount = 24;
bih.biCompression = BI_RGB;
bih.biXPelsPerMeter = 2835;
bih.biYPelsPerMeter = 2835;
bih.biClrUsed = 0;
bih.biClrImportant = 0;
COLORREF_RGB rgb;
rgb.cRed = 0;
rgb.cGreen = 0;
rgb.cBlue = 0;
BITMAPFILEHEADER bfh;
bfh.bfType = 0x424D;
bfh.bfReserved1 = 0;
bfh.bfReserved2 = 0;
bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + bih.biSize;
bfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
bih.biWidth * bih.biHeight * 4;
FILE *f;
f = fopen("test.bmp","wb");
fwrite(&bfh, sizeof(BITMAPFILEHEADER), 1, f);
fwrite(&bih, sizeof(BITMAPINFOHEADER), 1, f);
int i,j;
for(i = 0; i < bih.biHeight; i++)
{
for(j = 0; j < bih.biWidth; j++)
{
fwrite(&rgb,sizeof(COLORREF_RGB),1,f);
}
}
fclose(f);
return 0;
}
and jet every time I compile and run it I get error saying that its not valid BMP image. I double checked all values in multiple references and still can't find error here.
Did I misunderstood something and what am I doing wrong here?
Also not sure if important but I am using Ubuntu 14.04 to compile this.
EDIT
Found one more issue :
bfh.bfType = 0x424D;
should be
bfh.bfType = 0x4D42;
But still can't see image.
First of all, you set:
bfSize Specifies the size of the file, in bytes.
to invalid value, your code resulted into 1440112 while size of file is actually 1080112
bfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
bih.biWidth * bih.biHeight * sizeof(COLORREF_RGB);
Because sizeof(COLORREF_RGB) is actually 4 not 3.
Another mistake is that size of your structs and types:
expected size actual size*
typedef unsigned int UINT; // 2 4
typedef unsigned long DWORD; // 4 8
typedef long int LONG; // 4 8
typedef unsigned short WORD; // 2 2
typedef unsigned char BYTE; // 1 1
* I'm using gcc on x86_64 architecture
Your offsets just don't match with offsets on wikipedia, reference you are using was probably written for 16 bit compiler on 16 bit OS (as pointed out by cup in a comment) so it assumes int to be 2B type.
Using values from stdint.h worked for me (guide on stdint.h for Visual Studio here):
#include <stdint.h>
typedef uint16_t UINT;
typedef uint32_t DWORD;
typedef int32_t LONG;
typedef uint16_t WORD;
typedef uint8_t BYTE;
And last but not least you have to turn off memory alignment as suggested by Weather Vane.
I believe your field sizes to be incorrect, try this
#pragma pack(push, 1)
typedef struct tagBITMAPFILEHEADER {
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER;
#pragma pack(pop)
You are trying to map a C structure to some externally-defined binary format There are a number of problems with this:
Size
typedef unsigned int UINT;
typedef unsigned long DWORD;
typedef long int LONG;
typedef unsigned short WORD;
typedef unsigned char BYTE;
The C language only specify the minimum sizes of these types. Their actual sizes can and do vary between different compilers and operating systems. The sizes and offset of the members in your structures may not be what you expect. The only size that you can rely on (on almost any system that you are likely to encounter these days) is char being 8 bits.
Padding
typedef struct tagBITMAPFILEHEADER {
UINT bfType;
DWORD bfSize;
UINT bfReserved1;
UINT bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER;
It is common for DWORD to be twice as large as a UINT, and in fact your program depends on it. This usually means that the compiler will introduce padding between bfType and bfSize to give the latter appropriate alignment for its type. The .bmp format has no such padding.
Order
BITMAPFILEHEADER bfh;
bfh.bfType = 0x424D;
...
fwrite(&bfh, sizeof(BITMAPFILEHEADER), 1, f);
Another problem is that the C language does not specify the endianess of the types. The .bfType member may be stored as [42][4D] (Big-Endian) or [4D][42] (Little-Endian) in memory. The .bmp format specifically requires the values to be stored in Little-Endian order.
Solution
You might be able to solve some of these problems by using compiler-specific extensions (such as #pragma's or compiler switches), but probably not all of them.
The only way to properly write an externally-defined binary format, is to use an array of unsigned char and write the values a byte at a time. Personally, I would write a set of helper functions for specific types:
void w32BE (unsigned char *p, unsigned long ul)
{
p[0] = (ul >> 24) & 0xff;
p[1] = (ul >> 16) & 0xff;
p[2] = (ul >> 8) & 0xff;
p[3] = (ul ) & 0xff;
}
void w32LE (unsigned char *p, unsigned long ul)
{
p[0] = (ul ) & 0xff;
p[1] = (ul >> 8) & 0xff;
p[2] = (ul >> 16) & 0xff;
p[3] = (ul >> 24) & 0xff;
}
/* And so on */
and some functions for writing the entire .bmp file or sections of it:
int function write_header (FILE *f, BITMAPFILEHEADER bfh)
{
unsigned char buf[14];
w16LE (buf , bfh.bfType);
w32LE (buf+ 2, bfh.bfSize);
w16LE (buf+ 6, bfh.bfReserved1);
w16LE (buf+ 8, bfh.bfReserved2);
w32LE (buf+10, bfh.bfOffBits);
return fwrite (buf, sizeof buf, 1, f);
}
So i have 2 structs:
struct cmd {
uint8_t a;
uint8_t b;
uint8_t c;
};
typedef struct someName{
uint8_t size;
struct cmd cmdID;
} someName_t;
And i got a char res[0] containing the string "0xabc".
This 0xabc need to be put inside the cmd struct.
But the problem is 0xabc is 12 bit (1010 1011 1100) so if i put this into the struct with only uint8_t a and uint8_t b it will work because it will "fit" into 16 bits. But i got uint8_t a, uint8_t b and uint8_t c so 24 bits and that is my problem..
I tried:
someName_t msg;
sscanf(res[0], "0x%x", &(msg.cmdID));
But this does not work. This does work however if i remove the uint8_t c variable from the struct because it then fits inside the remaining 16 bits..
So how can i get the value "0xabc" into this (24bit) struct without adjusting the struct.
If you have control of your input format, i.e. you can guarantee it will always be something like 0xabc, then you can try:
const char input[] = "0xabc";
uint32_t tmp;
sscanf(input, "0x%x", &tmp);
struct cmd cmdid;
cmdid.a = (tmp & 0xFF0000U) >> 16;
cmdid.b = (tmp & 0xFF00U) >> 8;
cmdid.c = (tmp & 0xFFU);
You could try changing struct cmd to:
struct cmd {
unsigned int c:4;
unsigned int b:4;
unsigned int a:4;
};
But YMMV depending on compiler. Works OK on MSVC++ 2010.
I create UDP packets (insert IP and UDP headers) and send across the UDP socket. I want to add a dummy RTP header to the packet that I create. I created the RTP structure and inserting the RTP header as below:
rtph->cc = 4
rtph->x = 1
rtph->p = 1
rtph->version = 2
rtph->pt = 7
rtph->m = 1
rtph->seq = 0
rtph->ts = random()
rtph->ssrc = 0
When I capture in the wireshasrk I get Unknown RTP Version 3.
Any help is appreciated
If you define your own struct in C for RTP you must take the byte order into account.
typedef struct _RTPHeader
{
//first byte
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
unsigned int CC:4; /* CC field */
unsigned int X:1; /* X field */
unsigned int P:1; /* padding flag */
unsigned int version:2;
#elif G_BYTE_ORDER == G_BIG_ENDIAN
unsigned int version:2;
unsigned int P:1; /* padding flag */
unsigned int X:1; /* X field */
unsigned int CC:4; /* CC field*/
#else
#error "G_BYTE_ORDER should be big or little endian."
#endif
//second byte
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
unsigned int PT:7; /* PT field */
unsigned int M:1; /* M field */
#elif G_BYTE_ORDER == G_BIG_ENDIAN
unsigned int M:1; /* M field */
unsigned int PT:7; /* PT field */
#else
#error "G_BYTE_ORDER should be big or little endian."
#endif
guint16 seq_num; /* length of the recovery */
guint32 TS; /* Timestamp */
guint32 ssrc;
} RTPHeader; //12 bytes
The struct must be 12 bytes long, so you need force the compiler to pack it into a 12bytes long struct and not padding it.
Also I would add a static assert to check at compile time weather the struct really 12 bytes long, so:
#ifdef __WIN32__
#define PACKED
#pragma pack(push,1)
#else
#define PACKED __attribute__ ((__packed__))
#endif
//---------------------- STATIC ASSERT ----------------------------------
//Source: http://www.pixelbeat.org/programming/gcc/static_assert.html
#define ASSERT_CONCAT_(a, b) a##b
#define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b)
/* These can't be used after statements in c89. */
#ifdef __COUNTER__
#define STATIC_ASSERT(e,m) \
;enum { ASSERT_CONCAT(static_assert_, __COUNTER__) = 1/(!!(e)) }
#else
/* This can't be used twice on the same line so ensure if using in headers
* that the headers are not included twice (by wrapping in #ifndef...#endif)
* Note it doesn't cause an issue when used on same line of separate modules
* compiled with gcc -combine -fwhole-program. */
#define STATIC_ASSERT(e,m) \
;enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(!!(e)) }
#endif
typedef struct _RTPHeader
{
//first byte
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
unsigned int CC:4; /* CC field */
unsigned int X:1; /* X field */
unsigned int P:1; /* padding flag */
unsigned int version:2;
#elif G_BYTE_ORDER == G_BIG_ENDIAN
unsigned int version:2;
unsigned int P:1; /* padding flag */
unsigned int X:1; /* X field */
unsigned int CC:4; /* CC field*/
#else
#error "G_BYTE_ORDER should be big or little endian."
#endif
//second byte
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
unsigned int PT:7; /* PT field */
unsigned int M:1; /* M field */
#elif G_BYTE_ORDER == G_BIG_ENDIAN
unsigned int M:1; /* M field */
unsigned int PT:7; /* PT field */
#else
#error "G_BYTE_ORDER should be big or little endian."
#endif
guint16 seq_num; /* length of the recovery */
guint32 TS; /* Timestamp */
guint32 ssrc;
} RTPHeader; //12 bytes
STATIC_ASSERT (sizeof (RTPHeader) == 12, "RTPHeader size doesn't seem to be cool.");
#ifdef __WIN32__
#pragma pack(pop)
#undef PACKED
#else
#undef PACKED
#endif
The version number must be 2 and then if you write to the bytes with this struct, like this:
char buffer[1400];
RTPHeader *rtph = (RTPHeader*) buffer;
rtph->version = 2;
then theoretically it would be ok.