summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--key.c152
-rw-r--r--key.h11
3 files changed, 147 insertions, 22 deletions
diff --git a/ChangeLog b/ChangeLog
index 3bf840f77..cde557363 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,6 +3,10 @@
3 - markus@cvs.openbsd.org 2001/03/11 13:25:36 3 - markus@cvs.openbsd.org 2001/03/11 13:25:36
4 [auth2.c key.c] 4 [auth2.c key.c]
5 debug 5 debug
6 - jakob@cvs.openbsd.org 2001/03/11 15:03:16
7 [key.c key.h]
8 add improved fingerprint functions. based on work by Carsten
9 Raskgaard <cara@int.tele.dk> and modified by me. ok markus@.
6 10
720010311 1120010311
8 - OpenBSD CVS Sync 12 - OpenBSD CVS Sync
@@ -4496,4 +4500,4 @@
4496 - Wrote replacements for strlcpy and mkdtemp 4500 - Wrote replacements for strlcpy and mkdtemp
4497 - Released 1.0pre1 4501 - Released 1.0pre1
4498 4502
4499$Id: ChangeLog,v 1.940 2001/03/11 20:01:55 mouring Exp $ 4503$Id: ChangeLog,v 1.941 2001/03/11 20:03:44 mouring Exp $
diff --git a/key.c b/key.c
index df6bb2679..d8f994b5f 100644
--- a/key.c
+++ b/key.c
@@ -32,7 +32,7 @@
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */ 33 */
34#include "includes.h" 34#include "includes.h"
35RCSID("$OpenBSD: key.c,v 1.18 2001/03/11 13:25:36 markus Exp $"); 35RCSID("$OpenBSD: key.c,v 1.19 2001/03/11 15:03:15 jakob Exp $");
36 36
37#include <openssl/evp.h> 37#include <openssl/evp.h>
38 38
@@ -153,19 +153,16 @@ key_equal(Key *a, Key *b)
153 return 0; 153 return 0;
154} 154}
155 155
156/* 156u_char*
157 * Generate key fingerprint in ascii format. 157key_fingerprint_raw(Key *k, enum fp_type dgst_type, size_t *dgst_raw_length)
158 * Based on ideas and code from Bjoern Groenvall <bg@sics.se>
159 */
160char *
161key_fingerprint(Key *k)
162{ 158{
163 static char retval[(EVP_MAX_MD_SIZE+1)*3];
164 u_char *blob = NULL; 159 u_char *blob = NULL;
160 u_char *retval = NULL;
165 int len = 0; 161 int len = 0;
166 int nlen, elen; 162 int nlen, elen;
167 163
168 retval[0] = '\0'; 164 *dgst_raw_length = 0;
165
169 switch (k->type) { 166 switch (k->type) {
170 case KEY_RSA1: 167 case KEY_RSA1:
171 nlen = BN_num_bytes(k->rsa->n); 168 nlen = BN_num_bytes(k->rsa->n);
@@ -183,29 +180,144 @@ key_fingerprint(Key *k)
183 return retval; 180 return retval;
184 break; 181 break;
185 default: 182 default:
186 fatal("key_fingerprint: bad key type %d", k->type); 183 fatal("key_fingerprint_raw: bad key type %d", k->type);
187 break; 184 break;
188 } 185 }
189 if (blob != NULL) { 186 if (blob != NULL) {
190 int i; 187 EVP_MD *md = NULL;
191 u_char digest[EVP_MAX_MD_SIZE];
192 EVP_MD *md = EVP_md5();
193 EVP_MD_CTX ctx; 188 EVP_MD_CTX ctx;
189
190 retval = xmalloc(EVP_MAX_MD_SIZE);
191
192 switch (dgst_type) {
193 case SSH_FP_MD5:
194 md = EVP_md5();
195 break;
196 case SSH_FP_SHA1:
197 md = EVP_sha1();
198 break;
199 default:
200 fatal("key_fingerprint_raw: bad digest type %d",
201 dgst_type);
202 }
203
194 EVP_DigestInit(&ctx, md); 204 EVP_DigestInit(&ctx, md);
195 EVP_DigestUpdate(&ctx, blob, len); 205 EVP_DigestUpdate(&ctx, blob, len);
196 EVP_DigestFinal(&ctx, digest, NULL); 206 EVP_DigestFinal(&ctx, retval, NULL);
197 for(i = 0; i < md->md_size; i++) { 207 *dgst_raw_length = md->md_size;
198 char hex[4];
199 snprintf(hex, sizeof(hex), "%02x:", digest[i]);
200 strlcat(retval, hex, sizeof(retval));
201 }
202 retval[strlen(retval) - 1] = '\0';
203 memset(blob, 0, len); 208 memset(blob, 0, len);
204 xfree(blob); 209 xfree(blob);
210 } else {
211 fatal("key_fingerprint_raw: blob is null");
205 } 212 }
206 return retval; 213 return retval;
207} 214}
208 215
216char*
217key_fingerprint_hex(u_char* dgst_raw, size_t dgst_raw_len)
218{
219 char *retval;
220 int i;
221
222 retval = xmalloc(dgst_raw_len * 3);
223 retval[0] = '\0';
224 for(i = 0; i < dgst_raw_len; i++) {
225 char hex[4];
226 snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]);
227 strlcat(retval, hex, dgst_raw_len * 3);
228 }
229 retval[(dgst_raw_len * 3) - 1] = '\0';
230 return retval;
231}
232
233char*
234key_fingerprint_bubblebabble(u_char* dgst_raw, size_t dgst_raw_len)
235{
236 char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
237 char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
238 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };
239 u_int rounds, idx, retval_idx, seed;
240 char *retval;
241
242 rounds = (dgst_raw_len / 2) + 1;
243 retval = xmalloc(sizeof(char) * (rounds*6));
244 seed = 1;
245 retval_idx = 0;
246 retval[retval_idx++] = 'x';
247 for (idx=0;idx<rounds;idx++) {
248 u_int idx0, idx1, idx2, idx3, idx4;
249 if ((idx + 1 < rounds) || (dgst_raw_len % 2 != 0)) {
250 idx0 = (((((u_int)(dgst_raw[2 * idx])) >> 6) & 3) +
251 seed) % 6;
252 idx1 = (((u_int)(dgst_raw[2 * idx])) >> 2) & 15;
253 idx2 = ((((u_int)(dgst_raw[2 * idx])) & 3) +
254 (seed / 6)) % 6;
255 retval[retval_idx++] = vowels[idx0];
256 retval[retval_idx++] = consonants[idx1];
257 retval[retval_idx++] = vowels[idx2];
258 if ((idx + 1) < rounds) {
259 idx3 = (((u_int)(dgst_raw[(2 * idx) + 1])) >> 4) & 15;
260 idx4 = (((u_int)(dgst_raw[(2 * idx) + 1]))) & 15;
261 retval[retval_idx++] = consonants[idx3];
262 retval[retval_idx++] = '-';
263 retval[retval_idx++] = consonants[idx4];
264 seed = ((seed * 5) +
265 ((((u_int)(dgst_raw[2 * idx])) * 7) +
266 ((u_int)(dgst_raw[(2 * idx) + 1])))) % 36;
267 }
268 } else {
269 idx0 = seed % 6;
270 idx1 = 16;
271 idx2 = seed / 6;
272 retval[retval_idx++] = vowels[idx0];
273 retval[retval_idx++] = consonants[idx1];
274 retval[retval_idx++] = vowels[idx2];
275 }
276 }
277 retval[retval_idx++] = 'x';
278 retval[retval_idx++] = '\0';
279 return retval;
280}
281
282char*
283key_fingerprint_ex(Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep)
284{
285 char *retval = NULL;
286 u_char *dgst_raw;
287 size_t dgst_raw_len;
288
289 dgst_raw = key_fingerprint_raw(k, dgst_type, &dgst_raw_len);
290 if (!dgst_raw)
291 fatal("key_fingerprint_ex: null value returned from key_fingerprint_raw()");
292 switch(dgst_rep) {
293 case SSH_FP_HEX:
294 retval = key_fingerprint_hex(dgst_raw, dgst_raw_len);
295 break;
296 case SSH_FP_BUBBLEBABBLE:
297 retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len);
298 break;
299 default:
300 fatal("key_fingerprint_ex: bad digest representation %d",
301 dgst_rep);
302 break;
303 }
304 memset(dgst_raw, 0, dgst_raw_len);
305 xfree(dgst_raw);
306 return retval;
307}
308
309char *
310key_fingerprint(Key *k)
311{
312 static char retval[(EVP_MAX_MD_SIZE + 1) * 3];
313 char *digest;
314
315 digest = key_fingerprint_ex(k, SSH_FP_MD5, SSH_FP_HEX);
316 strlcpy(retval, digest, sizeof(retval));
317 xfree(digest);
318 return retval;
319}
320
209/* 321/*
210 * Reads a multiple-precision integer in decimal from the buffer, and advances 322 * Reads a multiple-precision integer in decimal from the buffer, and advances
211 * the pointer. The integer must already be initialized. This function is 323 * the pointer. The integer must already be initialized. This function is
diff --git a/key.h b/key.h
index 23a763439..e46c06eab 100644
--- a/key.h
+++ b/key.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: key.h,v 1.9 2001/01/29 01:58:16 niklas Exp $ */ 1/* $OpenBSD: key.h,v 1.10 2001/03/11 15:03:16 jakob Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -36,6 +36,14 @@ enum types {
36 KEY_DSA, 36 KEY_DSA,
37 KEY_UNSPEC 37 KEY_UNSPEC
38}; 38};
39enum fp_type {
40 SSH_FP_SHA1,
41 SSH_FP_MD5
42};
43enum fp_rep {
44 SSH_FP_HEX,
45 SSH_FP_BUBBLEBABBLE
46};
39struct Key { 47struct Key {
40 int type; 48 int type;
41 RSA *rsa; 49 RSA *rsa;
@@ -46,6 +54,7 @@ Key *key_new(int type);
46Key *key_new_private(int type); 54Key *key_new_private(int type);
47void key_free(Key *k); 55void key_free(Key *k);
48int key_equal(Key *a, Key *b); 56int key_equal(Key *a, Key *b);
57char *key_fingerprint_ex(Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep);
49char *key_fingerprint(Key *k); 58char *key_fingerprint(Key *k);
50char *key_type(Key *k); 59char *key_type(Key *k);
51int key_write(Key *key, FILE *f); 60int key_write(Key *key, FILE *f);