Folks,
Trying to troubleshoot an issue with the base64 function below. About 2-3% of the requests that pass through this process return an incorrect (too short) base64output.
static const char *header_request_gce(request_rec *r, char *a)
{
char *tim = apr_palloc(r->pool, APR_RFC822_DATE_LEN);
apr_rfc822_date(tim, r->request_time);
char *uri = apr_psprintf(r->pool, "%s", r->uri);
char encode[32768];
//encode = malloc(strlen(tim)+strlen(uri)); /* make space for the new string (should check the return value ...) */
strcpy(encode, "GET\n\n\n");
strcat(encode, tim);
strcat(encode, "\n");
strcat(encode, uri);
unsigned int encode_length = strlen(encode);
unsigned char* result;
unsigned char* key = (unsigned char*) "2kcXHh+K+XLtI61/KIV3d1tVzOooTdeOqFii9osz";
static char res_hexstring[8192];
result = HMAC(EVP_sha1(), key, 40, encode, encode_length, NULL, NULL);
char *base64(const unsigned char *input, int length);
char *base64output = base64(result, strlen(result));
return base64output;
}
char *base64(const unsigned char *input, int length)
{
BIO *bmem, *b64;
BUF_MEM *bptr;
b64 = BIO_new(BIO_f_base64());
bmem = BIO_new(BIO_s_mem());
b64 = BIO_push(b64, bmem);
BIO_write(b64, input, length);
BIO_flush(b64);
BIO_get_mem_ptr(b64, &bptr);
char *buff = (char *)malloc(bptr->length);
memcpy(buff, bptr->data, bptr->length-1);
buff[bptr->length-1] = 0;
BIO_free_all(b64);
return buff;
}
The key above has been modified ofcourse, but kept in the correct character format
This line is incorrect:
char *base64output = base64(result, strlen(result));
The data (output from sha1) that you are encoding can contain the NUL byte which means strlen returns a number that is too small (with a probability of 1 - (255/256)^20 which is approximately 7.5%). Rather than call strlen you should just pass in the size as a constant. I believe that if you are just encoding a sha1 hash, the length will always be 20:
char *base64output = base64(result, 20);
There is probably a better way to get that length from an HMAC function or something (so that it updates automatically if you change the hashing algorithm), but I am, admittedly, not very familiar with the hashing functions you're using.
Related
Given the following function
UART_write(UART_Handle handle, const void *buffer, size_t size);
I want to send via uart a int8_t value ( log it )
What i tried:
int8_t value;
UART_write(uart, value, strlen(value));
const char *echoPrompt = (char *)value;
UART_write(uart, echoPrompt, sizeof(echoPrompt));
const char echoPrompt2[] = {value};
UART_write(uart, echoPrompt2, sizeof(echoPrompt2));
const char* buff = value;
UART_write(uart, value, strlen(value));
The best i got is logging the hex value
Exemple of how the uart_write function works: In orded to log "12" what I need to do is
const uint8_t value[] = {0x31, 0x32};
UART_write(uart, value, sizeof(value));
So my question is, how to log my int8_t variable ( I need to log negative numbers as well)
You will need to convert your integer to string.
snprintf is a standard way to do this, if your libc provides it.
Convert uint8_t to an ascii string C
Determine the maximum string size needed for any value of that type. Is there a better way to size a buffer for printing integers?
#define UINT_BUFFER10_SIZE(type) (1 + (CHAR_BIT*sizeof(type)*LOG10_2_N)/LOG10_2_D + 1)
Form the buffer
char buf[UINT_BUFFER10_SIZE(value)];
"Print" the uint8_t to the buffer.
int len = sprintf(buf, "%d", value);
// or pedantically
int len = snprintf(buf, sizeof buf, "%" PRId8, value); // see <inttypes.h>
assert(len >= 0 && (unsigned)len < sizeof buf);
Send it
UART_write(uart, buf, len);
how to log my int8_t variable
#define INT_BUFFER10_SIZE(type) (2 + ((CHAR_BIT*sizeof(type)-1)*LOG10_2_N)/LOG10_2_D + 1)
char buf[INT_BUFFER10_SIZE(ivalue)];
int len = sprintf(buf, "%d", ivalue);
UART_write(uart, buf, len);
IMO, code should add a helper function to send a string
void UART_write_str(UART_Handle handle, const char *str) {
UART_write(uart, str, strlen(str));
}
Here I am trying to get the size of bio file as ,
long res = BIO_get_mem_ptr(certBio, &bptr);
length = bptr->length; // is the length
I got this sample code from some stackoverflow question. I have tried many time but the BIO_get_mem_ptr is giving a null pointer in bptr with return value 0. I can't find any solutions related to this problem in any reference sites.
Here is the source code,
int pass_cb(char *buf, int size, int rwflag, void *u)
{
int len;
char *tmp;
tmp = "123456";
len = strlen(tmp);
if (len <= 0)
return 0;
if (len > size)
len = size;
memcpy(buf, tmp, len);
return len;
}
int main(void)
{
X509 *x509;
int length = 0;
unsigned char data[1000];
unsigned char *buffer = NULL;
buffer = data;
BIO *certBio = BIO_new(BIO_s_file());
// BIO *certBio = BIO_new(BIO_s_mem()); -> have tried this one too gives the same result
BUF_MEM *bptr = 0;
BIO_read_filename(certBio, "E:\\share\\Folder\\TempCert.pem");
x509 = PEM_read_bio_X509_AUX(certBio, NULL, pass_cb, NULL);
long res = BIO_get_mem_ptr(certBio, &bptr);
length = bptr->length;
memset(&buffer, 0, 1000);
int ret = BIO_read(certBio, &buffer, length);
BIO_free_all(certBio);
CertFreeCertificateContext(pContext);
CertCloseStore(hStore, 0);
return 0;
}
What is the problem causing here,
As you can see on The Man bio_get_mem_ptr wants a memory BIO
A memory BIO is a source/sink BIO which uses memory for its I/O. Data written to a memory BIO is stored in a BUF_MEM structure which is extended as appropriate to accommodate the stored data.
You are trying to use a file, so you should use the example code on The Man of bio_s_file
This is a continuation of my previous question: Intermittent decryption failures in EVP_DecryptFinal_ex when using AES-128/CBC.
I am trying to encrypt and decrypt using the C OpenSSL EVP library. After I received an answer to my question above, I updated my code accordingly:
This variable:
int len = outlen1 + outlen2;
Stores the number of bytes encrypted in the encrypt function. I then pass that variable to the decrypt function (the passing is not shown in the code below) which then uses what is supposedly the actual number of bytes.
However on some input strings, I get segmentation faults at the EVP_DecryptFinal_ex() function.
Something is obviously wrong with the number of bytes encrypted/decrypted or padding. I just don't know what that is.
char* encrypt(char *key, char *s) {
unsigned char iv[16] = {[0 ... 15 ] = 0};
unsigned char outbuf[1024] = {[0 ... 1023] = 0};
int outlen1, outlen2;
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv);
if (EVP_EncryptUpdate(&ctx, outbuf, &outlen1, s, strlen(s)) == 1) {
if (EVP_EncryptFinal_ex(&ctx, outbuf + outlen1, &outlen2) == 1) {
EVP_CIPHER_CTX_cleanup(&ctx);
len = outlen1 + outlen2;
return strdup(outbuf);
}
}
EVP_CIPHER_CTX_cleanup(&ctx);
return NULL;
}
char* decrypt(char *key, char *s, int len) {
unsigned char iv[16] = {[0 ... 15 ] = 0};
unsigned char outbuf[1024] = {[0 ... 1023] = 0};
int outlen1, outlen2;
printf("len: %d\n", len);
printf("strlen(s): %d\n", strlen(s));
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv);
if (EVP_DecryptUpdate(&ctx, outbuf, &outlen1, s, len) == 1) {
printf("After update\n");
if (EVP_DecryptFinal_ex(&ctx, outbuf + outlen1, &outlen2) == 1) {
printf("After final\n");
EVP_CIPHER_CTX_cleanup(&ctx);
return strdup(outbuf);
}
}
EVP_CIPHER_CTX_cleanup(&ctx);
return NULL;
}
NOTE:
I was able to fix the problems I previously had where decrypt final would fail to decrypt certain strings. Those strings can be decrypted fine now. However, some other strings are facing the same problem but this time I am getting seg faults.
You cannot use string functions on binary data. This is especially the case if that binary data is indistinguishable from random. Random binary data may contain null characters anywhere, or not at all. strdup uses strcpy internally, which relies on the null character to be present.
I'm using OpenSSL BlowFish and encountering something very strange. My functions are below:
char* BFEncrypt(char* key, char* text)
{
char ivec[EVP_MAX_IV_LENGTH] = {0};
int len = strlen(text);
char *cipher = (char*)malloc(sizeof(char)*(len+1));
int *num = (int*)malloc(sizeof(int));
*num = 0;
BF_KEY *bfkey = (BF_KEY*)malloc(sizeof(BF_KEY));
BF_set_key(bfkey, strlen(key), key);
BF_cfb64_encrypt(text, cipher, len, bfkey, ivec, num, BF_ENCRYPT);
cipher[len] = '\0';
free(num);
free(bfkey);
return cipher;
}
char* BFDecrypt(char* key, char* cipher)
{
char ivec[EVP_MAX_IV_LENGTH] = {0};
int len = strlen(cipher);
char *text = (char*)malloc(sizeof(char)*(len+1));
int *num = (int*)malloc(sizeof(int));
*num = 0;
BF_KEY *bfkey = (BF_KEY*)malloc(sizeof(BF_KEY));
BF_set_key(bfkey, strlen(key), key);
BF_cfb64_encrypt(cipher, text, len, bfkey, ivec, num, BF_DECRYPT);
text[len] = '\0';
free(num);
free(bfkey);
return text;
}
If I did something as below in a function, I can obtain the right plaintext from decryption:
char *plainText1;
char *key1;
//initialize those pointers
char *cipher1 = BFEncrypt(key1, plainText1);
char *temp = BFDecrypt(key1, cipher1); //here I test that temp is equal to plainText1
However, in a different function, if I only invoke the BFDecrypt, I would not be able to get the same plaintext before:
//somehow I stored the cipher1 above in my disk and read it
char *cipher2; //store cipher1
char *key2;// key2 is equal to key1
char *plaintext2 = BFDecrypct(key2, cipher2); //Here is the problem!!!!! plaintext2 is not equal to plaintext1
The confusing part is, even if key2 and cipher2 is exactly the same as key1 and cipher1 , plaintext2 is completely different with plaintext1. Could anyone give me a hint, I stuck on this for a long time.
Thanks in advance!
I want to convert data in other encodings to UTF-8. I'm stranded with following problems:
Executing the attached code gives me: pointer being freed was not allocated in iconv().
Why does iconv play with my memory?
When I don't free(dst) it doesn't crash but nothing is printed. Not even gibberish.
What's wrong?
void utf8(char **dst, char **src, const char *enc)
{
iconv_t cd;
size_t len_src,
len_dst;
len_src = strlen(*src);
len_dst = len_src * 8; // is that enough for ASCII to UTF8?
cd = iconv_open("UTF-8", enc);
*dst = (char *)calloc(len_dst+1, 1);
iconv(cd, src, &len_src, dst, &len_dst);
iconv_close(cd);
}
int main(int argc, char **argv)
{
char *src = "hello world";
char *dst;
utf8(&dst, &src, "ASCII");
printf("%s\n", dst);
free(dst);
return 0;
}
Quote from iconv() description at POSIX.1-2008
size_t iconv(iconv_t cd, char **restrict inbuf,
size_t *restrict inbytesleft, char **restrict outbuf,
size_t *restrict outbytesleft);
The variable pointed to by outbuf shall be updated to point to the byte following the last byte of converted output data.
You need to save and restore *dst (and possibly *src) inside your utf8() function.