diff options
Diffstat (limited to 'key.c')
-rw-r--r-- | key.c | 117 |
1 files changed, 116 insertions, 1 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: key.c,v 1.69 2007/07/12 05:48:05 ray Exp $ */ | 1 | /* $OpenBSD: key.c,v 1.78 2008/07/07 23:32:51 stevesk Exp $ */ |
2 | /* | 2 | /* |
3 | * read_bignum(): | 3 | * read_bignum(): |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -11,6 +11,7 @@ | |||
11 | * | 11 | * |
12 | * | 12 | * |
13 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. | 13 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. |
14 | * Copyright (c) 2008 Alexander von Gernler. All rights reserved. | ||
14 | * | 15 | * |
15 | * Redistribution and use in source and binary forms, with or without | 16 | * Redistribution and use in source and binary forms, with or without |
16 | * modification, are permitted provided that the following conditions | 17 | * modification, are permitted provided that the following conditions |
@@ -35,9 +36,11 @@ | |||
35 | 36 | ||
36 | #include "includes.h" | 37 | #include "includes.h" |
37 | 38 | ||
39 | #include <sys/param.h> | ||
38 | #include <sys/types.h> | 40 | #include <sys/types.h> |
39 | 41 | ||
40 | #include <openssl/evp.h> | 42 | #include <openssl/evp.h> |
43 | #include <openbsd-compat/openssl-compat.h> | ||
41 | 44 | ||
42 | #include <stdarg.h> | 45 | #include <stdarg.h> |
43 | #include <stdio.h> | 46 | #include <stdio.h> |
@@ -171,6 +174,7 @@ key_equal(const Key *a, const Key *b) | |||
171 | default: | 174 | default: |
172 | fatal("key_equal: bad key type %d", a->type); | 175 | fatal("key_equal: bad key type %d", a->type); |
173 | } | 176 | } |
177 | /* NOTREACHED */ | ||
174 | } | 178 | } |
175 | 179 | ||
176 | u_char* | 180 | u_char* |
@@ -294,6 +298,114 @@ key_fingerprint_bubblebabble(u_char *dgst_raw, u_int dgst_raw_len) | |||
294 | return retval; | 298 | return retval; |
295 | } | 299 | } |
296 | 300 | ||
301 | /* | ||
302 | * Draw an ASCII-Art representing the fingerprint so human brain can | ||
303 | * profit from its built-in pattern recognition ability. | ||
304 | * This technique is called "random art" and can be found in some | ||
305 | * scientific publications like this original paper: | ||
306 | * | ||
307 | * "Hash Visualization: a New Technique to improve Real-World Security", | ||
308 | * Perrig A. and Song D., 1999, International Workshop on Cryptographic | ||
309 | * Techniques and E-Commerce (CrypTEC '99) | ||
310 | * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf | ||
311 | * | ||
312 | * The subject came up in a talk by Dan Kaminsky, too. | ||
313 | * | ||
314 | * If you see the picture is different, the key is different. | ||
315 | * If the picture looks the same, you still know nothing. | ||
316 | * | ||
317 | * The algorithm used here is a worm crawling over a discrete plane, | ||
318 | * leaving a trace (augmenting the field) everywhere it goes. | ||
319 | * Movement is taken from dgst_raw 2bit-wise. Bumping into walls | ||
320 | * makes the respective movement vector be ignored for this turn. | ||
321 | * Graphs are not unambiguous, because circles in graphs can be | ||
322 | * walked in either direction. | ||
323 | */ | ||
324 | |||
325 | /* | ||
326 | * Field sizes for the random art. Have to be odd, so the starting point | ||
327 | * can be in the exact middle of the picture, and FLDBASE should be >=8 . | ||
328 | * Else pictures would be too dense, and drawing the frame would | ||
329 | * fail, too, because the key type would not fit in anymore. | ||
330 | */ | ||
331 | #define FLDBASE 8 | ||
332 | #define FLDSIZE_Y (FLDBASE + 1) | ||
333 | #define FLDSIZE_X (FLDBASE * 2 + 1) | ||
334 | static char * | ||
335 | key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key *k) | ||
336 | { | ||
337 | /* | ||
338 | * Chars to be used after each other every time the worm | ||
339 | * intersects with itself. Matter of taste. | ||
340 | */ | ||
341 | char *augmentation_string = " .o+=*BOX@%&#/^SE"; | ||
342 | char *retval, *p; | ||
343 | u_char field[FLDSIZE_X][FLDSIZE_Y]; | ||
344 | u_int i, b; | ||
345 | int x, y; | ||
346 | size_t len = strlen(augmentation_string) - 1; | ||
347 | |||
348 | retval = xcalloc(1, (FLDSIZE_X + 3) * (FLDSIZE_Y + 2)); | ||
349 | |||
350 | /* initialize field */ | ||
351 | memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char)); | ||
352 | x = FLDSIZE_X / 2; | ||
353 | y = FLDSIZE_Y / 2; | ||
354 | |||
355 | /* process raw key */ | ||
356 | for (i = 0; i < dgst_raw_len; i++) { | ||
357 | int input; | ||
358 | /* each byte conveys four 2-bit move commands */ | ||
359 | input = dgst_raw[i]; | ||
360 | for (b = 0; b < 4; b++) { | ||
361 | /* evaluate 2 bit, rest is shifted later */ | ||
362 | x += (input & 0x1) ? 1 : -1; | ||
363 | y += (input & 0x2) ? 1 : -1; | ||
364 | |||
365 | /* assure we are still in bounds */ | ||
366 | x = MAX(x, 0); | ||
367 | y = MAX(y, 0); | ||
368 | x = MIN(x, FLDSIZE_X - 1); | ||
369 | y = MIN(y, FLDSIZE_Y - 1); | ||
370 | |||
371 | /* augment the field */ | ||
372 | field[x][y]++; | ||
373 | input = input >> 2; | ||
374 | } | ||
375 | } | ||
376 | |||
377 | /* mark starting point and end point*/ | ||
378 | field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1; | ||
379 | field[x][y] = len; | ||
380 | |||
381 | /* fill in retval */ | ||
382 | snprintf(retval, FLDSIZE_X, "+--[%4s %4u]", key_type(k), key_size(k)); | ||
383 | p = strchr(retval, '\0'); | ||
384 | |||
385 | /* output upper border */ | ||
386 | for (i = p - retval - 1; i < FLDSIZE_X; i++) | ||
387 | *p++ = '-'; | ||
388 | *p++ = '+'; | ||
389 | *p++ = '\n'; | ||
390 | |||
391 | /* output content */ | ||
392 | for (y = 0; y < FLDSIZE_Y; y++) { | ||
393 | *p++ = '|'; | ||
394 | for (x = 0; x < FLDSIZE_X; x++) | ||
395 | *p++ = augmentation_string[MIN(field[x][y], len)]; | ||
396 | *p++ = '|'; | ||
397 | *p++ = '\n'; | ||
398 | } | ||
399 | |||
400 | /* output lower border */ | ||
401 | *p++ = '+'; | ||
402 | for (i = 0; i < FLDSIZE_X; i++) | ||
403 | *p++ = '-'; | ||
404 | *p++ = '+'; | ||
405 | |||
406 | return retval; | ||
407 | } | ||
408 | |||
297 | char * | 409 | char * |
298 | key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep) | 410 | key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep) |
299 | { | 411 | { |
@@ -311,6 +423,9 @@ key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep) | |||
311 | case SSH_FP_BUBBLEBABBLE: | 423 | case SSH_FP_BUBBLEBABBLE: |
312 | retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len); | 424 | retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len); |
313 | break; | 425 | break; |
426 | case SSH_FP_RANDOMART: | ||
427 | retval = key_fingerprint_randomart(dgst_raw, dgst_raw_len, k); | ||
428 | break; | ||
314 | default: | 429 | default: |
315 | fatal("key_fingerprint_ex: bad digest representation %d", | 430 | fatal("key_fingerprint_ex: bad digest representation %d", |
316 | dgst_rep); | 431 | dgst_rep); |