From: Nikos Mavrogiannopoulos Date: Wed, 28 Dec 2011 14:12:17 +0000 (+0200) Subject: Added function gnutls_random_art() to convert fingerprints to images (currently ascii... X-Git-Tag: gnutls_3_0_10~44 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=78bf1de9b111485037388893bf2ccc766f8d167d;p=thirdparty%2Fgnutls.git Added function gnutls_random_art() to convert fingerprints to images (currently ascii-art). --- diff --git a/NEWS b/NEWS index c04f2c80f7..be88c61c48 100644 --- a/NEWS +++ b/NEWS @@ -12,8 +12,11 @@ in Linux as well as in BSD. ** libgnutls: Added ciphersuites: GNUTLS_PSK_WITH_AES_256_GCM_SHA384 and GNUTLS_DHE_PSK_WITH_AES_256_GCM_SHA384. +** libgnutls: Added function gnutls_random_art() to convert +fingerprints to images (currently ascii-art). + ** API and ABI modifications: -No changes since last version. +gnutls_random_art: Added * Version 3.0.9 (released 2011-12-13) diff --git a/configure.ac b/configure.ac index 2d3a359e08..ebc8625653 100644 --- a/configure.ac +++ b/configure.ac @@ -465,6 +465,7 @@ AC_CONFIG_FILES([ lib/algorithms/Makefile lib/auth/Makefile lib/ext/Makefile + lib/extras/Makefile lib/gnutls.pc lib/includes/Makefile lib/includes/gnutls/gnutls.h diff --git a/lib/Makefile.am b/lib/Makefile.am index d944c2f708..7fd533adab 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -20,7 +20,7 @@ ACLOCAL_AMFLAGS = -I ../m4 -I ../gl/m4 -SUBDIRS = includes x509 accelerated auth ext algorithms +SUBDIRS = includes x509 accelerated auth ext algorithms extras if ENABLE_MINITASN1 SUBDIRS += minitasn1 endif @@ -114,6 +114,7 @@ libgnutls_la_LDFLAGS = -no-undefined \ libgnutls_la_LIBADD = ../gl/libgnu.la x509/libgnutls_x509.la \ accelerated/libaccelerated.la ext/libgnutls_ext.la \ auth/libgnutls_auth.la algorithms/libgnutls_alg.la \ + extras/libgnutls_extras.la \ $(LTLIBZ) $(LTLIBINTL) $(LIBSOCKET) $(LTLIBDL) \ $(LTLIBPTHREAD) $(P11_KIT_LIBS) diff --git a/lib/extras/Makefile.am b/lib/extras/Makefile.am new file mode 100644 index 0000000000..b973b88d45 --- /dev/null +++ b/lib/extras/Makefile.am @@ -0,0 +1,37 @@ +## Process this file with automake to produce Makefile.in +# Copyright (C) 2002-2011 Free Software Foundation, Inc. +# +# Author: Nikos Mavrogiannopoulos +# +# This file is part of GnuTLS. +# +# The GnuTLS is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# The GnuTLS is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see + +AM_CFLAGS = $(WERROR_CFLAGS) $(WSTACK_CFLAGS) $(WARN_CFLAGS) +AM_CPPFLAGS = \ + -I$(srcdir)/../../gl \ + -I$(builddir)/../../gl \ + -I$(srcdir)/../includes \ + -I$(builddir)/../includes \ + -I$(builddir)/../../gl \ + -I$(srcdir)/.. \ + -I$(srcdir)/../opencdk + +if ENABLE_MINITASN1 +AM_CPPFLAGS += -I$(srcdir)/../minitasn1 +endif + +noinst_LTLIBRARIES = libgnutls_extras.la + +libgnutls_extras_la_SOURCES = randomart.c diff --git a/lib/extras/randomart.c b/lib/extras/randomart.c new file mode 100644 index 0000000000..c2ce08f4b0 --- /dev/null +++ b/lib/extras/randomart.c @@ -0,0 +1,147 @@ +/* $OpenBSD: key.c,v 1.98 2011/10/18 04:58:26 djm Exp $ */ +/* + * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. + * Copyright (c) 2008 Alexander von Gernler. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#include +#include +#include + +/* + * Draw an ASCII-Art representing the fingerprint so human brain can + * profit from its built-in pattern recognition ability. + * This technique is called "random art" and can be found in some + * scientific publications like this original paper: + * + * "Hash Visualization: a New Technique to improve Real-World Security", + * Perrig A. and Song D., 1999, International Workshop on Cryptographic + * Techniques and E-Commerce (CrypTEC '99) + * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf + * + * The subject came up in a talk by Dan Kaminsky, too. + * + * If you see the picture is different, the key is different. + * If the picture looks the same, you still know nothing. + * + * The algorithm used here is a worm crawling over a discrete plane, + * leaving a trace (augmenting the field) everywhere it goes. + * Movement is taken from dgst_raw 2bit-wise. Bumping into walls + * makes the respective movement vector be ignored for this turn. + * Graphs are not unambiguous, because circles in graphs can be + * walked in either direction. + */ + +/* + * Field sizes for the random art. Have to be odd, so the starting point + * can be in the exact middle of the picture, and FLDBASE should be >=8 . + * Else pictures would be too dense, and drawing the frame would + * fail, too, because the key type would not fit in anymore. + */ +#define FLDBASE 8 +#define FLDSIZE_Y (FLDBASE + 1) +#define FLDSIZE_X (FLDBASE * 2 + 1) +char * +key_fingerprint_randomart (uint8_t * dgst_raw, u_int dgst_raw_len, + const char *key_type, unsigned int key_size) +{ + /* + * Chars to be used after each other every time the worm + * intersects with itself. Matter of taste. + */ + const char augmentation_string[] = " .o+=*BOX@%&#/^SE"; + char *retval, *p; + uint8_t field[FLDSIZE_X][FLDSIZE_Y]; + u_int i, b; + int x, y; + const size_t len = sizeof(augmentation_string) - 1; + + retval = gnutls_calloc (1, (FLDSIZE_X + 3) * (FLDSIZE_Y + 2)); + if (retval == NULL) + { + gnutls_assert(); + return NULL; + } + + /* initialize field */ + memset (field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof (char)); + x = FLDSIZE_X / 2; + y = FLDSIZE_Y / 2; + + /* process raw key */ + for (i = 0; i < dgst_raw_len; i++) + { + int input; + /* each byte conveys four 2-bit move commands */ + input = dgst_raw[i]; + for (b = 0; b < 4; b++) + { + /* evaluate 2 bit, rest is shifted later */ + x += (input & 0x1) ? 1 : -1; + y += (input & 0x2) ? 1 : -1; + + /* assure we are still in bounds */ + x = MAX (x, 0); + y = MAX (y, 0); + x = MIN (x, FLDSIZE_X - 1); + y = MIN (y, FLDSIZE_Y - 1); + + /* augment the field */ + if (field[x][y] < len - 2) + field[x][y]++; + input = input >> 2; + } + } + + /* mark starting point and end point */ + field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1; + field[x][y] = len; + + /* fill in retval */ + snprintf (retval, FLDSIZE_X, "+--[%4s %4u]", key_type, key_size); + p = strchr (retval, '\0'); + + /* output upper border */ + for (i = p - retval - 1; i < FLDSIZE_X; i++) + *p++ = '-'; + *p++ = '+'; + *p++ = '\n'; + + /* output content */ + for (y = 0; y < FLDSIZE_Y; y++) + { + *p++ = '|'; + for (x = 0; x < FLDSIZE_X; x++) + *p++ = augmentation_string[MIN (field[x][y], len)]; + *p++ = '|'; + *p++ = '\n'; + } + + /* output lower border */ + *p++ = '+'; + for (i = 0; i < FLDSIZE_X; i++) + *p++ = '-'; + *p++ = '+'; + + return retval; +} diff --git a/lib/extras/randomart.h b/lib/extras/randomart.h new file mode 100644 index 0000000000..77d912b492 --- /dev/null +++ b/lib/extras/randomart.h @@ -0,0 +1,3 @@ +char * +key_fingerprint_randomart (uint8_t * dgst_raw, u_int dgst_raw_len, + const char *key_type, unsigned int key_size); diff --git a/lib/gnutls_ui.c b/lib/gnutls_ui.c index edf80c0965..6205a91381 100644 --- a/lib/gnutls_ui.c +++ b/lib/gnutls_ui.c @@ -34,6 +34,40 @@ #include #include #include +#include + +/** + * gnutls_random_art: + * @type: The type of the random art + * @key_type: The type of the key (RSA, DSA etc.) + * @key_size: The size of the key in bits + * @fpr: The fingerprint of the key + * @fpr_size: The size of the fingerprint + * @art: The returned random art + * + * This function will convert a given fingerprint to an "artistic" + * image. The returned image is allocated using gnutls_malloc() + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise + * an error code is returned. + * + **/ +int gnutls_random_art (gnutls_random_art_t type, + const char* key_type, unsigned int key_size, + void * fpr, size_t fpr_size, + gnutls_datum_t* art) +{ + if (type != GNUTLS_RANDOM_ART_OPENSSH) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + art->data = key_fingerprint_randomart(fpr, fpr_size, key_type, key_size); + if (art->data == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + + art->size = strlen(art->data); + + return 0; +} /* ANON & DHE */ diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index 2906eaad3d..3080dd0172 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -1268,13 +1268,21 @@ gnutls_ecc_curve_t gnutls_ecc_curve_get(gnutls_session_t session); void gnutls_openpgp_send_cert (gnutls_session_t session, gnutls_openpgp_crt_status_t status); -/* fingerprint - * Actually this function returns the hash of the given data. +/* This function returns the hash of the given data. */ int gnutls_fingerprint (gnutls_digest_algorithm_t algo, const gnutls_datum_t * data, void *result, size_t * result_size); + typedef enum gnutls_random_art + { + GNUTLS_RANDOM_ART_OPENSSH=1, + } gnutls_random_art_t; + + int gnutls_random_art (gnutls_random_art_t type, + const char* key_name, unsigned int key_size, + void * fpr, size_t fpr_size, + gnutls_datum_t* art); /* SRP */ diff --git a/lib/libgnutls.map b/lib/libgnutls.map index 24f04f0d74..04772105db 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -726,6 +726,7 @@ GNUTLS_3_0_0 { gnutls_srp_4096_group_prime; gnutls_x509_privkey_verify_params; gnutls_priority_get_cipher_suite_index; + gnutls_random_art; } GNUTLS_2_12; GNUTLS_PRIVATE { diff --git a/lib/openpgp/output.c b/lib/openpgp/output.c index 2b5f12d592..defcf95f04 100644 --- a/lib/openpgp/output.c +++ b/lib/openpgp/output.c @@ -26,6 +26,7 @@ #include #include #include +#include /* I18n of error codes. */ #include "gettext.h" @@ -88,6 +89,7 @@ print_key_id (gnutls_buffer_st * str, gnutls_openpgp_crt_t cert, int idx) _gnutls_buffer_hexprint (str, id, sizeof (id)); addf (str, "\n"); } + } /* idx == -1 indicates main key @@ -99,6 +101,9 @@ print_key_fingerprint (gnutls_buffer_st * str, gnutls_openpgp_crt_t cert) char fpr[128]; size_t fpr_size = sizeof (fpr); int err; + const char* name; + char* p; + unsigned int bits; err = gnutls_openpgp_crt_get_fingerprint (cert, fpr, &fpr_size); if (err < 0) @@ -109,6 +114,24 @@ print_key_fingerprint (gnutls_buffer_st * str, gnutls_openpgp_crt_t cert) _gnutls_buffer_hexprint (str, fpr, fpr_size); addf (str, "\n"); } + + err = gnutls_openpgp_crt_get_pk_algorithm (cert, &bits); + if (err < 0) + return; + + name = gnutls_pk_get_name(err); + if (name == NULL) + return; + + p = key_fingerprint_randomart(fpr, fpr_size, name, bits); + if (p == NULL) + return; + + adds (str, _("\trandomart:\n")); + adds (str, p); + adds (str, "\n"); + + gnutls_free(p); } static void diff --git a/lib/x509/output.c b/lib/x509/output.c index b0e8640966..894f56a112 100644 --- a/lib/x509/output.c +++ b/lib/x509/output.c @@ -29,6 +29,7 @@ #include #include #include +#include /* I18n of error codes. */ #include "gettext.h" @@ -1348,7 +1349,10 @@ print_fingerprint (gnutls_buffer_st * str, gnutls_x509_crt_t cert, int err; char buffer[MAX_HASH_SIZE]; size_t size = sizeof (buffer); - + const char* name; + char* p; + unsigned int bits; + err = gnutls_x509_crt_get_fingerprint (cert, algo, buffer, &size); if (err < 0) { @@ -1362,6 +1366,24 @@ print_fingerprint (gnutls_buffer_st * str, gnutls_x509_crt_t cert, adds (str, _("\tSHA-1 fingerprint:\n\t\t")); _gnutls_buffer_hexprint (str, buffer, size); adds (str, "\n"); + + err = gnutls_x509_crt_get_pk_algorithm (cert, &bits); + if (err < 0) + return; + + name = gnutls_pk_get_name(err); + if (name == NULL) + return; + + p = key_fingerprint_randomart(buffer, size, name, bits); + if (p == NULL) + return; + + adds (str, _("\trandomart:\n")); + adds (str, p); + adds (str, "\n"); + + gnutls_free(p); } static void