Line data Source code
1 : /* $OpenBSD: key.c,v 1.98 2011/10/18 04:58:26 djm Exp $ */
2 : /*
3 : * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
4 : * Copyright (c) 2008 Alexander von Gernler. All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions
8 : * are met:
9 : * 1. Redistributions of source code must retain the above copyright
10 : * notice, this list of conditions and the following disclaimer.
11 : * 2. Redistributions in binary form must reproduce the above copyright
12 : * notice, this list of conditions and the following disclaimer in the
13 : * documentation and/or other materials provided with the distribution.
14 : *
15 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 : * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 : */
26 :
27 : #include "gnutls_int.h"
28 : #include "errors.h"
29 : #include <randomart.h>
30 :
31 : /*
32 : * Draw an ASCII-Art representing the fingerprint so human brain can
33 : * profit from its built-in pattern recognition ability.
34 : * This technique is called "random art" and can be found in some
35 : * scientific publications like this original paper:
36 : *
37 : * "Hash Visualization: a New Technique to improve Real-World Security",
38 : * Perrig A. and Song D., 1999, International Workshop on Cryptographic
39 : * Techniques and E-Commerce (CrypTEC '99)
40 : * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf
41 : *
42 : * The subject came up in a talk by Dan Kaminsky, too.
43 : *
44 : * If you see the picture is different, the key is different.
45 : * If the picture looks the same, you still know nothing.
46 : *
47 : * The algorithm used here is a worm crawling over a discrete plane,
48 : * leaving a trace (augmenting the field) everywhere it goes.
49 : * Movement is taken from dgst_raw 2bit-wise. Bumping into walls
50 : * makes the respective movement vector be ignored for this turn.
51 : * Graphs are not unambiguous, because circles in graphs can be
52 : * walked in either direction.
53 : */
54 :
55 : /*
56 : * Field sizes for the random art. Have to be odd, so the starting point
57 : * can be in the exact middle of the picture, and FLDBASE should be >=8 .
58 : * Else pictures would be too dense, and drawing the frame would
59 : * fail, too, because the key type would not fit in anymore.
60 : */
61 : #define FLDBASE 8
62 : #define FLDSIZE_Y (FLDBASE + 1)
63 : #define FLDSIZE_X (FLDBASE * 2 + 1)
64 3 : char *_gnutls_key_fingerprint_randomart(uint8_t * dgst_raw,
65 : u_int dgst_raw_len,
66 : const char *key_type,
67 : unsigned int key_size,
68 : const char *prefix)
69 : {
70 : /*
71 : * Chars to be used after each other every time the worm
72 : * intersects with itself. Matter of taste.
73 : */
74 3 : const char augmentation_string[] = " .o+=*BOX@%&#/^SE";
75 3 : char *retval, *p;
76 3 : uint8_t field[FLDSIZE_X][FLDSIZE_Y];
77 3 : char size_txt[16];
78 3 : unsigned int i, b;
79 3 : int x, y;
80 3 : const size_t len = sizeof(augmentation_string) - 2;
81 3 : unsigned int prefix_len = 0;
82 :
83 3 : if (prefix)
84 0 : prefix_len = strlen(prefix);
85 :
86 3 : retval =
87 6 : gnutls_calloc(1,
88 3 : (FLDSIZE_X + 3 + prefix_len) * (FLDSIZE_Y + 2));
89 3 : if (retval == NULL) {
90 0 : gnutls_assert();
91 0 : return NULL;
92 : }
93 :
94 : /* initialize field */
95 3 : memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));
96 3 : x = FLDSIZE_X / 2;
97 3 : y = FLDSIZE_Y / 2;
98 :
99 : /* process raw key */
100 75 : for (i = 0; i < dgst_raw_len; i++) {
101 72 : int input;
102 : /* each byte conveys four 2-bit move commands */
103 72 : input = dgst_raw[i];
104 360 : for (b = 0; b < 4; b++) {
105 : /* evaluate 2 bit, rest is shifted later */
106 288 : x += (input & 0x1) ? 1 : -1;
107 288 : y += (input & 0x2) ? 1 : -1;
108 :
109 : /* assure we are still in bounds */
110 288 : x = MAX(x, 0);
111 288 : y = MAX(y, 0);
112 288 : x = MIN(x, FLDSIZE_X - 1);
113 288 : y = MIN(y, FLDSIZE_Y - 1);
114 :
115 : /* augment the field */
116 288 : if (field[x][y] < len - 2)
117 288 : field[x][y]++;
118 288 : input = input >> 2;
119 : }
120 : }
121 :
122 : /* mark starting point and end point */
123 3 : field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1;
124 3 : field[x][y] = len;
125 :
126 3 : if (key_size > 0)
127 3 : snprintf(size_txt, sizeof(size_txt), " %4u", key_size);
128 : else
129 0 : size_txt[0] = 0;
130 :
131 : /* fill in retval */
132 3 : if (prefix_len)
133 0 : snprintf(retval, FLDSIZE_X + prefix_len, "%s+--[%4s%s]",
134 : prefix, key_type, size_txt);
135 : else
136 3 : snprintf(retval, FLDSIZE_X, "+--[%4s%s]", key_type,
137 : size_txt);
138 3 : p = strchr(retval, '\0');
139 :
140 : /* output upper border */
141 14 : for (i = p - retval - 1; i < FLDSIZE_X + prefix_len; i++)
142 11 : *p++ = '-';
143 3 : *p++ = '+';
144 3 : *p++ = '\n';
145 :
146 3 : if (prefix_len) {
147 0 : memcpy(p, prefix, prefix_len);
148 0 : p += prefix_len;
149 : }
150 :
151 : /* output content */
152 30 : for (y = 0; y < FLDSIZE_Y; y++) {
153 27 : *p++ = '|';
154 486 : for (x = 0; x < FLDSIZE_X; x++)
155 459 : *p++ = augmentation_string[MIN(field[x][y], len)];
156 27 : *p++ = '|';
157 27 : *p++ = '\n';
158 :
159 27 : if (prefix_len) {
160 0 : memcpy(p, prefix, prefix_len);
161 0 : p += prefix_len;
162 : }
163 : }
164 :
165 : /* output lower border */
166 3 : *p++ = '+';
167 54 : for (i = 0; i < FLDSIZE_X; i++)
168 51 : *p++ = '-';
169 3 : *p++ = '+';
170 :
171 3 : return retval;
172 : }
|