Blame lib/extras/randomart.c

Packit Service 4684c1
/* $OpenBSD: key.c,v 1.98 2011/10/18 04:58:26 djm Exp $ */
Packit Service 4684c1
/*
Packit Service 4684c1
 * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
Packit Service 4684c1
 * Copyright (c) 2008 Alexander von Gernler.  All rights reserved.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Redistribution and use in source and binary forms, with or without
Packit Service 4684c1
 * modification, are permitted provided that the following conditions
Packit Service 4684c1
 * are met:
Packit Service 4684c1
 * 1. Redistributions of source code must retain the above copyright
Packit Service 4684c1
 *    notice, this list of conditions and the following disclaimer.
Packit Service 4684c1
 * 2. Redistributions in binary form must reproduce the above copyright
Packit Service 4684c1
 *    notice, this list of conditions and the following disclaimer in the
Packit Service 4684c1
 *    documentation and/or other materials provided with the distribution.
Packit Service 4684c1
 *
Packit Service 4684c1
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
Packit Service 4684c1
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
Packit Service 4684c1
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
Packit Service 4684c1
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
Packit Service 4684c1
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
Packit Service 4684c1
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit Service 4684c1
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit Service 4684c1
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit Service 4684c1
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
Packit Service 4684c1
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit Service 4684c1
 */
Packit Service 4684c1
Packit Service 4684c1
#include "gnutls_int.h"
Packit Service 4684c1
#include "errors.h"
Packit Service 4684c1
#include <randomart.h>
Packit Service 4684c1
Packit Service 4684c1
/*
Packit Service 4684c1
 * Draw an ASCII-Art representing the fingerprint so human brain can
Packit Service 4684c1
 * profit from its built-in pattern recognition ability.
Packit Service 4684c1
 * This technique is called "random art" and can be found in some
Packit Service 4684c1
 * scientific publications like this original paper:
Packit Service 4684c1
 *
Packit Service 4684c1
 * "Hash Visualization: a New Technique to improve Real-World Security",
Packit Service 4684c1
 * Perrig A. and Song D., 1999, International Workshop on Cryptographic
Packit Service 4684c1
 * Techniques and E-Commerce (CrypTEC '99)
Packit Service 4684c1
 * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf
Packit Service 4684c1
 *
Packit Service 4684c1
 * The subject came up in a talk by Dan Kaminsky, too.
Packit Service 4684c1
 *
Packit Service 4684c1
 * If you see the picture is different, the key is different.
Packit Service 4684c1
 * If the picture looks the same, you still know nothing.
Packit Service 4684c1
 *
Packit Service 4684c1
 * The algorithm used here is a worm crawling over a discrete plane,
Packit Service 4684c1
 * leaving a trace (augmenting the field) everywhere it goes.
Packit Service 4684c1
 * Movement is taken from dgst_raw 2bit-wise.  Bumping into walls
Packit Service 4684c1
 * makes the respective movement vector be ignored for this turn.
Packit Service 4684c1
 * Graphs are not unambiguous, because circles in graphs can be
Packit Service 4684c1
 * walked in either direction.
Packit Service 4684c1
 */
Packit Service 4684c1
Packit Service 4684c1
/*
Packit Service 4684c1
 * Field sizes for the random art.  Have to be odd, so the starting point
Packit Service 4684c1
 * can be in the exact middle of the picture, and FLDBASE should be >=8 .
Packit Service 4684c1
 * Else pictures would be too dense, and drawing the frame would
Packit Service 4684c1
 * fail, too, because the key type would not fit in anymore.
Packit Service 4684c1
 */
Packit Service 4684c1
#define	FLDBASE		8
Packit Service 4684c1
#define	FLDSIZE_Y	(FLDBASE + 1)
Packit Service 4684c1
#define	FLDSIZE_X	(FLDBASE * 2 + 1)
Packit Service 4684c1
char *_gnutls_key_fingerprint_randomart(uint8_t * dgst_raw,
Packit Service 4684c1
					u_int dgst_raw_len,
Packit Service 4684c1
					const char *key_type,
Packit Service 4684c1
					unsigned int key_size,
Packit Service 4684c1
					const char *prefix)
Packit Service 4684c1
{
Packit Service 4684c1
	/*
Packit Service 4684c1
	 * Chars to be used after each other every time the worm
Packit Service 4684c1
	 * intersects with itself.  Matter of taste.
Packit Service 4684c1
	 */
Packit Service 4684c1
	const char augmentation_string[] = " .o+=*BOX@%&#/^SE";
Packit Service 4684c1
	char *retval, *p;
Packit Service 4684c1
	uint8_t field[FLDSIZE_X][FLDSIZE_Y];
Packit Service 4684c1
	char size_txt[16];
Packit Service 4684c1
	unsigned int i, b;
Packit Service 4684c1
	int x, y;
Packit Service 4684c1
	const size_t len = sizeof(augmentation_string) - 2;
Packit Service 4684c1
	unsigned int prefix_len = 0;
Packit Service 4684c1
Packit Service 4684c1
	if (prefix)
Packit Service 4684c1
		prefix_len = strlen(prefix);
Packit Service 4684c1
Packit Service 4684c1
	retval =
Packit Service 4684c1
	    gnutls_calloc(1,
Packit Service 4684c1
			  (FLDSIZE_X + 3 + prefix_len) * (FLDSIZE_Y + 2));
Packit Service 4684c1
	if (retval == NULL) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		return NULL;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	/* initialize field */
Packit Service 4684c1
	memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));
Packit Service 4684c1
	x = FLDSIZE_X / 2;
Packit Service 4684c1
	y = FLDSIZE_Y / 2;
Packit Service 4684c1
Packit Service 4684c1
	/* process raw key */
Packit Service 4684c1
	for (i = 0; i < dgst_raw_len; i++) {
Packit Service 4684c1
		int input;
Packit Service 4684c1
		/* each byte conveys four 2-bit move commands */
Packit Service 4684c1
		input = dgst_raw[i];
Packit Service 4684c1
		for (b = 0; b < 4; b++) {
Packit Service 4684c1
			/* evaluate 2 bit, rest is shifted later */
Packit Service 4684c1
			x += (input & 0x1) ? 1 : -1;
Packit Service 4684c1
			y += (input & 0x2) ? 1 : -1;
Packit Service 4684c1
Packit Service 4684c1
			/* assure we are still in bounds */
Packit Service 4684c1
			x = MAX(x, 0);
Packit Service 4684c1
			y = MAX(y, 0);
Packit Service 4684c1
			x = MIN(x, FLDSIZE_X - 1);
Packit Service 4684c1
			y = MIN(y, FLDSIZE_Y - 1);
Packit Service 4684c1
Packit Service 4684c1
			/* augment the field */
Packit Service 4684c1
			if (field[x][y] < len - 2)
Packit Service 4684c1
				field[x][y]++;
Packit Service 4684c1
			input = input >> 2;
Packit Service 4684c1
		}
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	/* mark starting point and end point */
Packit Service 4684c1
	field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1;
Packit Service 4684c1
	field[x][y] = len;
Packit Service 4684c1
Packit Service 4684c1
	if (key_size > 0)
Packit Service 4684c1
		snprintf(size_txt, sizeof(size_txt), " %4u", key_size);
Packit Service 4684c1
	else
Packit Service 4684c1
		size_txt[0] = 0;
Packit Service 4684c1
Packit Service 4684c1
	/* fill in retval */
Packit Service 4684c1
	if (prefix_len)
Packit Service 4684c1
		snprintf(retval, FLDSIZE_X + prefix_len, "%s+--[%4s%s]",
Packit Service 4684c1
			 prefix, key_type, size_txt);
Packit Service 4684c1
	else
Packit Service 4684c1
		snprintf(retval, FLDSIZE_X, "+--[%4s%s]", key_type,
Packit Service 4684c1
			 size_txt);
Packit Service 4684c1
	p = strchr(retval, '\0');
Packit Service 4684c1
Packit Service 4684c1
	/* output upper border */
Packit Service 4684c1
	for (i = p - retval - 1; i < FLDSIZE_X + prefix_len; i++)
Packit Service 4684c1
		*p++ = '-';
Packit Service 4684c1
	*p++ = '+';
Packit Service 4684c1
	*p++ = '\n';
Packit Service 4684c1
Packit Service 4684c1
	if (prefix_len) {
Packit Service 4684c1
		memcpy(p, prefix, prefix_len);
Packit Service 4684c1
		p += prefix_len;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	/* output content */
Packit Service 4684c1
	for (y = 0; y < FLDSIZE_Y; y++) {
Packit Service 4684c1
		*p++ = '|';
Packit Service 4684c1
		for (x = 0; x < FLDSIZE_X; x++)
Packit Service 4684c1
			*p++ = augmentation_string[MIN(field[x][y], len)];
Packit Service 4684c1
		*p++ = '|';
Packit Service 4684c1
		*p++ = '\n';
Packit Service 4684c1
Packit Service 4684c1
		if (prefix_len) {
Packit Service 4684c1
			memcpy(p, prefix, prefix_len);
Packit Service 4684c1
			p += prefix_len;
Packit Service 4684c1
		}
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	/* output lower border */
Packit Service 4684c1
	*p++ = '+';
Packit Service 4684c1
	for (i = 0; i < FLDSIZE_X; i++)
Packit Service 4684c1
		*p++ = '-';
Packit Service 4684c1
	*p++ = '+';
Packit Service 4684c1
Packit Service 4684c1
	return retval;
Packit Service 4684c1
}