Base64 with OpenSSL in C

Assuming that you have already built OpenSSL for Windows. Check this guide for details.

Link your project with this library from OpenSSL, libeay32.lib.

Definitions and Includes:

#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
#include <stdbool.h>
 
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/buffer.h>
 
bool Base64Encode(char **dest, const char *src, unsigned int slen);
bool Base64Decode(char **dest, const char *src);
unsigned int countDecodedLength(const char *encoded);

Base64 Encoding:

bool Base64Encode(char **dest, const char *src, unsigned int slen){
	if (src == NULL || slen <= 0) return false;
 
	BIO *bio, *b64;
	BUF_MEM *bufferPtr;
 
	b64 = BIO_new(BIO_f_base64());
        if (!b64) return false;
 
	bio = BIO_new(BIO_s_mem());
        if (!bio) return false;
 
	bio = BIO_push(b64, bio);
        if (!bio) return false;
 
	BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
 
	if (BIO_write(bio, src, slen) <= 0) {
            if (bio) BIO_free_all(bio);
            return false;
        }
 
	if (1 != BIO_flush(bio)) {
            if (bio) BIO_free_all(bio);
            return false;
        }
 
	BIO_get_mem_ptr(bio, &bufferPtr);
 
	BIO_set_close(bio, BIO_NOCLOSE);
 
	if (bio) BIO_free_all(bio);
 
	*dest = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (*bufferPtr).length + 1);
	if (*dest == NULL) return false;
 
	strncpy_s(*dest, (*bufferPtr).length + 1, (*bufferPtr).data, (*bufferPtr).length);
 
	return true;
}

Base64 Decoding:

bool Base64Decode(char **dest, const char *src){
	if (src == NULL) return false;
	unsigned int dlen = 0;
	BIO *bio, *b64;
 
	unsigned int decode_length = countDecodedLength(src);
 
	*dest = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, decode_length + 1);
	if (*dest == NULL) return false;
 
	bio = BIO_new_mem_buf((char*)src, -1);
        if (!bio) return false;
 
	b64 = BIO_new(BIO_f_base64());
        if (!b64 ) return false;
 
	bio = BIO_push(b64, bio);
        if (!bio) return false;
 
	BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
 
	dlen = BIO_read(bio, *dest, strlen(src));
 
	if (dlen != decode_length){
		if (dest){
			HeapFree(GetProcessHeap(), 0, dest);
			dest = NULL;
		}
		if (bio) BIO_free_all(bio);
		return false;
	}
 
        if (bio) BIO_free_all(bio);
 
        *(*dest + decodeLen) = '\0';
 
	return true;
}
 
unsigned int countDecodedLength(const char *encoded) {
	if (encoded == NULL) return 0;
	unsigned int len = strlen(encoded), padding = 0;
 
	if (encoded[len - 1] == '=' && encoded[len - 2] == '=')
		padding = 2;
	else if (encoded[len - 1] == '=')
		padding = 1;
 
	return (len * 3) / 4 - padding;
}

Usage:

int main(void){
	char *encoded, *decoded;
	const char plain[] = "maldevel\0";
 
	if(Base64Encode(&encoded, plain, strlen(plain)))
	    printf("base64 encoded text: %s\n", encoded);
 
	if(Base64Decode(&decoded, encoded))
	    printf("plain text: %s\n", decoded);
 
	if (encoded){
	    HeapFree(GetProcessHeap(), 0, encoded);
	    encoded = NULL;
	}
	if (decoded){
	    HeapFree(GetProcessHeap(), 0, decoded);
	    decoded = NULL;
	}
 
	return EXIT_SUCCESS;
}
Categories: C Tags: , , ,
%d bloggers like this: