24
Mar
2012

Crypto++: cifrar bloque binario con AES + ECB

Crypto++ es una de las bibliotecas más importantes y recomendables para implementar funciones criptográficas en C++. Es de uso libre (open source) y funciona en múltiples plataformas (Windows, Linux, OS X). Si en algún momento deciden usarla, tomenlo con paciencia porque es un poco árida al principio.

En el día de hoy comencé a implementar una demo de CTR (streamcipher) en Qt/C++. Para esta implementación -que no es tan compleja-, necesité aplicar un blockcipher a bloques binarios de largo fijo. Elegí como blockcipher al algoritmo Rijndael. Como no era el objetivo implementar un Rijndael desde cero, decidí utilizar la funcionalidad que brinda Crypto++ (cryptopp).

Para facilitar el asunto, voy a estar trabajando con bloques y claves de 128 bits (16 bytes).

Al cifrar un único bloque de largo fijo e igual a 128 bits, no necesito padding ni técnicas de block-chaining (ej. CBC). Por lo tanto, el modo en el que necesitaba usar AES es ECB sin padding. Recordemos que ECB no encadena bloques realmente y en caso de que el texto plano se repita, se repetirá también el cifrado leakeando información. Por favor nunca utilizar ECB para cifrar mensajes de más de un bloque.

Hechas estas consideraciones, este es el código:


Leer el resto del artículo »

3
Mar
2011

mtrace: debug de memoria en C (LibC)

La función mtrace proporcionada por LibC nos permite trazar todos las operaciones de obtención, redimensionamiento y liberación de memoria realizadas por las funciones malloc, realloc y free respectivamente. De esta forma, es posible detectar memory leaks (memoria sin liberar) en nuestra aplicación.

La función mtrace se vale de la variable de entorno MALLOC_TRACE para conocer la ruta donde guardar el resultado de las operaciones realizadas.

Con la función muntrace podemos detener el monitoreo iniciado por mtrace. Es posible encapsular bloques del programa con mtrace y muntrace.

Código de ejemplo:

#include <stdio .h>
#include <stdlib .h>
#include <mcheck .h>
 
int main () {
 
	setenv("MALLOC_TRACE", "/root/c/mtrace/output", 1);
 
	mtrace();
 
	void* puntero_a_memoria =  (void*)malloc(1);
 
	return 0;
}
</mcheck></stdlib></stdio>

Cambien el path /root/c/mtrace/out por el que les resulte conveniente. El proceso debe tener permisos de escritura allí.


Leer el resto del artículo »

3
Mar
2011

Variables de entorno con LibC

LibC provee algunas funciones para manejar las variables de entorno. Debemos incluir la Standard Library (stdlib.h) para acceder a ellas.

Limpiar las variables de entorno:

int clearenv(void);

Escribir o modificar una variable de entorno:

int putenv(char *string);

El parámetro string es de la forma VARIABLE=valor

Escribir o modificar una variable de entorno:

int setenv(const char *name, const char *value, int overwrite);

name es el nombre de la variable de entorno, value el valor y overwrite (0 o número distinto de 0) permite especificar la acción para el caso de que la variable de entorno ya exista con un valor determinado.

Remover una variable de entorno:

int unsetenv(const char *name);

name es el nombre de la variable de entorno.

2
Feb
2011

Debug de memoria en C con mcheck() y mprobe()

Comparto aquí un código con el que estuve haciendo algunas pruebas para debuguear memoria en C. Lo que hace es forzar errores escribiendo memoria no reservada y utilizar las funciones mcheck() y mprobe() de la librería GNU Libc para obtener información del error.

#include <stdio .h>
#include <stdlib .h>
#include <string .h>
#include <mcheck .h>
#include <malloc .h>
 
void error_memoria (enum mcheck_status estado_mcheck);
 
void error_memoria(enum mcheck_status estado_mcheck){
	printf("Llamada ocasional de mcheck() a error_memoria()\n");
}
 
main()
{
	//Chequeos de memoria ocasionales con mcheck
	int r = mcheck(error_memoria);
	if(r == 0)
		printf("Llamada a mcheck() ok\n");
	else if(r == -1)
		printf("Llamada a mcheck() tardía\n");
 
	//Reservar memoria y setearla en NULL para un array de chars de 6 lugares
	char* array_chars = (char*)malloc(sizeof(char)*6);
	memset(array_chars, '\0', 6);
 
	//Cargar esos lugares con el string "hola"
	strcpy(array_chars, "hola");
 
	//Iterar para obtener las direcciones de memoria y sus valores del array + 5 lugares fuera del array
	int i;
	for(i=0; i < sizeof(array_chars) + 5; i++){
		printf("Direccion %c: %x\n", array_chars[i], (int)&array_chars[i]);
 
		//Escribir fuera del array con valores NULL
		if(i >= sizeof(array_chars)){
			//Comentar esta línea para evitar este tipo de error
			array_chars[i] = '\0';
		}
	}
 
	//Obtener la direccion de memoria anterior al array y cargarle el valor NULL
	int mem0 = ((int)&array_chars[0]) - 1;
        char* ptr = (char*)mem0;
	//Descomentar esta línea para forzar la escritura anterior al bloque.
        //*ptr = '\0';
 
	//Descomentar esta línea para forzar un error del tipo 'memoria ya liberada'	
        //free(array_chars);
 
	//Realizar una comprobación de memoria con mprobe() al array de chars
	enum mcheck_status estado = mprobe(array_chars);
	switch (estado){
		case MCHECK_DISABLED:
			printf("Estado disabled: mcheck no fue llamado al principio. No se puede hacer una comprobación coherente de memoria.\n");
			break;
		case MCHECK_OK:
			printf("Estado ok: no hay inconsistencias detectadas\n");
			break;
		case MCHECK_HEAD:
			printf("Estado head: los datos inmediatamente anteriores al bloque reservado fueron modificados.\n");
			break;
		case MCHECK_TAIL:
			printf("Estado tail: los datos inmediatamente posteriores al bloque fueron modificados.\n");
			break;
		case MCHECK_FREE:
			printf("Estado free: el bloque ya fue liberado\n");
			break;
		default:
			break;
	}
}
</malloc></mcheck></string></stdlib></stdio>


Leer el resto del artículo »