From: Pekka Riikonen Date: Tue, 8 Jan 2008 07:49:48 +0000 (+0000) Subject: Fixed printable fingerprint buffer overflow. RedHat bug 372021. X-Git-Tag: 1.2.beta1~32 X-Git-Url: http://git.silcnet.org/gitweb/?p=crypto.git;a=commitdiff_plain;h=f7e22d7feb85bcee3738c52c7649d4077441c3f6 Fixed printable fingerprint buffer overflow. RedHat bug 372021. --- diff --git a/CHANGES.RUNTIME b/CHANGES.RUNTIME index b7b5e2f4..9ce124dd 100644 --- a/CHANGES.RUNTIME +++ b/CHANGES.RUNTIME @@ -1,3 +1,8 @@ +Tue Jan 8 09:41:57 EET 2008 Pekka Riikonen + + * Fixed printable fingerprint bufferoverlfow, RedHat bug 372021. + Affected file is lib/silcutil/silcutil.c. + Sat Jan 5 20:19:28 EET 2008 Pekka Riikonen * Added SILC_STR_DELETE buffer format macro. Added support for diff --git a/lib/silcutil/silcutil.c b/lib/silcutil/silcutil.c index eb0d989e..07688e36 100644 --- a/lib/silcutil/silcutil.c +++ b/lib/silcutil/silcutil.c @@ -332,28 +332,43 @@ SilcBool silc_hash_client_id_compare(void *key1, void *key2, char *silc_fingerprint(const unsigned char *data, SilcUInt32 data_len) { - char fingerprint[64], *cp; - int i; + unsigned char *fingerprint, *cp; + unsigned int len, blocks, i; + + if (!data || !data_len) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return NULL; + } + + if (data_len >= 256) + data_len = 255; + + /* Align and calculate total length */ + len = ((data_len + 19) / 20) * 20; + blocks = (len / 10); + len = (len * 2) + ((blocks - 1) * 2) + (4 * blocks) + 2 + 1; + + cp = fingerprint = silc_calloc(len, sizeof(*fingerprint)); + if (!cp) + return NULL; - memset(fingerprint, 0, sizeof(fingerprint)); - cp = fingerprint; for (i = 0; i < data_len; i++) { - silc_snprintf(cp, sizeof(fingerprint), "%02X", data[i]); + silc_snprintf(cp, len, "%02X", data[i]); cp += 2; + len -= 2; if ((i + 1) % 2 == 0) - silc_snprintf(cp++, sizeof(fingerprint), " "); - + silc_snprintf(cp++, len--, " "); if ((i + 1) % 10 == 0) - silc_snprintf(cp++, sizeof(fingerprint), " "); + silc_snprintf(cp++, len--, " "); } i--; - if ((i + 1) % 2 == 0) - cp[-2] = 0; if ((i + 1) % 10 == 0) - cp[-1] = 0; + *(--cp) = '\0'; + if ((i + 1) % 2 == 0) + *(--cp) = '\0'; - return silc_strdup(fingerprint); + return fingerprint; } /* Return TRUE if the `data' is ASCII string. */ diff --git a/lib/silcutil/silcutil.h b/lib/silcutil/silcutil.h index 7aa40a4f..4524a80b 100644 --- a/lib/silcutil/silcutil.h +++ b/lib/silcutil/silcutil.h @@ -213,7 +213,9 @@ SilcBool silc_hash_client_id_compare(void *key1, void *key2, * DESCRIPTION * * Return a textual representation of the fingerprint in *data, the - * caller must free the returned string. + * caller must free the returned string. Returns NULL on error. If + * the `data_len' is longer than 255 bytes, only the first 255 bytes are + * used to create the fingerprint. * ***/ char *silc_fingerprint(const unsigned char *data, SilcUInt32 data_len);