From: Pekka Riikonen Date: Sun, 1 Dec 2002 15:14:00 +0000 (+0000) Subject: Changed private key file encryptio process. Added temporary X-Git-Tag: silc.client.0.9.10~44 X-Git-Url: http://git.silcnet.org/gitweb/?a=commitdiff_plain;h=cfe0677aedbe5f8d96f973b6cc621e1964ed5ef1;p=silc.git Changed private key file encryptio process. Added temporary backwards support too and automatic change from the old to new. --- diff --git a/CHANGES b/CHANGES index 246834d1..1c1b0eea 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,20 @@ +Sun Dec 1 18:17:22 EET 2002 Pekka Riikonen + + * Added test vectors and test programs for SHA-1, MD5, + HMAC-SHA1 and HMAC-MD5. New tests are located in + lib/silccrypt/tests/. Fixed also argument decoding bug in + MD5 implementation. Affected file lib/silccrypt/md5.c. + + * Changed the channel private key and private message key + generation (with static keys) to use SHA1 instead of MD5, + as SHA1 is the mandatory hash function in SILC. Affected + file lib/silcclient/client_[channel/prvmsg].c. + + * Changed the private key file encryption to use SHA1 instead + of MD5. Added support for the old generation and added + automatic change of the key (to be removed later). Affected + files lib/silccrypt/silcpkcs.c. + Sat Nov 30 19:07:52 EET 2002 Pekka Riikonen * Load only files with .pub suffix in PublicKeyDir. Affected diff --git a/lib/silccrypt/silcpkcs.c b/lib/silccrypt/silcpkcs.c index 1038d621..6e31c00d 100644 --- a/lib/silccrypt/silcpkcs.c +++ b/lib/silccrypt/silcpkcs.c @@ -1187,7 +1187,7 @@ static bool silc_pkcs_save_private_key_internal(const char *filename, SilcUInt32 encoding) { SilcCipher aes; - SilcHash md5; + SilcHash sha1; SilcHmac sha1hmac; SilcBuffer buf, enc; SilcUInt32 len, blocklen; @@ -1206,9 +1206,9 @@ static bool silc_pkcs_save_private_key_internal(const char *filename, if (blocklen * 2 > sizeof(tmp)) return FALSE; - /* Allocate MD5 hash */ - if (!silc_hash_alloc("md5", &md5)) { - SILC_LOG_ERROR(("Could not allocate MD5 hash, probably not registered")); + /* Allocate SHA1 hash */ + if (!silc_hash_alloc("sha1", &sha1)) { + SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered")); silc_cipher_free(aes); return FALSE; } @@ -1216,7 +1216,7 @@ static bool silc_pkcs_save_private_key_internal(const char *filename, /* Allocate HMAC */ if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) { SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered")); - silc_hash_free(md5); + silc_hash_free(sha1); silc_cipher_free(aes); return FALSE; } @@ -1225,13 +1225,13 @@ static bool silc_pkcs_save_private_key_internal(const char *filename, is 256 bits length, and derived by taking hash of the data, then re-hashing the data and the previous digest, and using the first and second digest as the key. */ - silc_hash_init(md5); - silc_hash_update(md5, key, key_len); - silc_hash_final(md5, keymat); - silc_hash_init(md5); - silc_hash_update(md5, key, key_len); - silc_hash_update(md5, keymat, 16); - silc_hash_final(md5, keymat + 16); + silc_hash_init(sha1); + silc_hash_update(sha1, key, key_len); + silc_hash_final(sha1, keymat); + silc_hash_init(sha1); + silc_hash_update(sha1, key, key_len); + silc_hash_update(sha1, keymat, 16); + silc_hash_final(sha1, keymat + 16); /* Set the key to the cipher */ silc_cipher_set_key(aes, keymat, sizeof(keymat) * 8); @@ -1245,7 +1245,7 @@ static bool silc_pkcs_save_private_key_internal(const char *filename, (blocklen + (data_len % blocklen)) + len); if (!enc) { silc_hmac_free(sha1hmac); - silc_hash_free(md5); + silc_hash_free(sha1); silc_cipher_free(aes); return FALSE; } @@ -1285,7 +1285,7 @@ static bool silc_pkcs_save_private_key_internal(const char *filename, memset(keymat, 0, sizeof(keymat)); memset(tmp, 0, sizeof(tmp)); silc_hmac_free(sha1hmac); - silc_hash_free(md5); + silc_hash_free(sha1); silc_cipher_free(aes); data = enc->data; @@ -1407,6 +1407,156 @@ bool silc_pkcs_load_public_key(const char *filename, SilcPublicKey *public_key, return TRUE; } +#if 1 /* Old MD5 routine for private key loading, remove later! */ +struct MD5Context { + SilcUInt32 buf[4]; + SilcUInt32 bits[2]; + unsigned char in[64]; +}; +static void MD5Init(struct MD5Context *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + ctx->bits[0] = ctx->bits[1] = 0; +} +static void +MD5Transform(SilcUInt32 buf[4], const unsigned char kbuf[64]); +static void +MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) +{ + SilcUInt32 t; + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((SilcUInt32)len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += (SilcUInt32)len >> 29; + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + if ( t ) { + unsigned char *p = (unsigned char *)ctx->in + t; + + t = 64-t; + if (len < t) { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + MD5Transform(ctx->buf, ctx->in); + buf += t; + len -= t; + } while (len >= 64) { + memcpy(ctx->in, buf, 64); + MD5Transform(ctx->buf, ctx->in); + buf += 64; + len -= 64; + } + memcpy(ctx->in, buf, len); +} + +static void MD5Final(unsigned char digest[16], struct MD5Context *ctx) +{ + unsigned count; + unsigned char *p; + count = (ctx->bits[0] >> 3) & 0x3F; + p = ctx->in + count; + *p++ = 0x80; + count = 64 - 1 - count; + if (count < 8) { + memset(p, 0, count); + MD5Transform(ctx->buf, ctx->in); + memset(ctx->in, 0, 56); + } else { + memset(p, 0, count-8); + } + ((SilcUInt32 *)ctx->in)[ 14 ] = ctx->bits[0]; + ((SilcUInt32 *)ctx->in)[ 15 ] = ctx->bits[1]; + MD5Transform(ctx->buf, ctx->in); + memcpy(digest, ctx->buf, 16); + memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ +} +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) +static void +MD5Transform(SilcUInt32 buf[4], const unsigned char kbuf[64]) +{ + register SilcUInt32 a, b, c, d, i; + SilcUInt32 in[16]; + for (i = 0; i < 16; i++) + SILC_GET32_MSB(in[i], kbuf + 4 * i); + a = buf[0]; b = buf[1]; c = buf[2]; d = buf[3]; + MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22); + MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20); + MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23); + MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21); + buf[0] += a; buf[1] += b; buf[2] += c; buf[3] += d; +} +#endif /* 1 */ + /* Load private key from file and allocates new private key. Returns TRUE if loading was successful. */ @@ -1417,13 +1567,23 @@ bool silc_pkcs_load_private_key(const char *filename, SilcUInt32 encoding) { SilcCipher aes; - SilcHash md5; + SilcHash sha1; SilcHmac sha1hmac; SilcUInt32 blocklen; unsigned char tmp[32], keymat[32]; unsigned char *cp, *old, *data, byte; SilcUInt32 i, data_len, len, magic, mac_len; +#if 1 + /* Old support */ + struct MD5Context md5; + bool oldsupport = FALSE; +#endif /* 1 */ + + SILC_LOG_DEBUG(("Loading private key `%s' with %s encoding", filename, + encoding == SILC_PKCS_FILE_PEM ? "Base64" : + encoding == SILC_PKCS_FILE_BIN ? "Binary" : "Unkonwn")); + old = data = silc_file_readfile(filename, &data_len); if (!data) return FALSE; @@ -1494,9 +1654,9 @@ bool silc_pkcs_load_private_key(const char *filename, return FALSE; } - /* Allocate MD5 hash */ - if (!silc_hash_alloc("md5", &md5)) { - SILC_LOG_ERROR(("Could not allocate MD5 hash, probably not registered")); + /* Allocate SHA1 hash */ + if (!silc_hash_alloc("sha1", &sha1)) { + SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered")); silc_cipher_free(aes); memset(old, 0, data_len); silc_free(old); @@ -1506,7 +1666,7 @@ bool silc_pkcs_load_private_key(const char *filename, /* Allocate HMAC */ if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) { SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered")); - silc_hash_free(md5); + silc_hash_free(sha1); silc_cipher_free(aes); memset(old, 0, data_len); silc_free(old); @@ -1517,14 +1677,28 @@ bool silc_pkcs_load_private_key(const char *filename, is 256 bits length, and derived by taking hash of the data, then re-hashing the data and the previous digest, and using the first and second digest as the key. */ - silc_hash_init(md5); - silc_hash_update(md5, passphrase, passphrase_len); - silc_hash_final(md5, keymat); - silc_hash_init(md5); - silc_hash_update(md5, passphrase, passphrase_len); - silc_hash_update(md5, keymat, 16); - silc_hash_final(md5, keymat + 16); + silc_hash_init(sha1); + silc_hash_update(sha1, passphrase, passphrase_len); + silc_hash_final(sha1, keymat); + silc_hash_init(sha1); + silc_hash_update(sha1, passphrase, passphrase_len); + silc_hash_update(sha1, keymat, 16); + silc_hash_final(sha1, keymat + 16); +#if 1 + olds: + /* Old support */ + if (oldsupport) { + MD5Init(&md5); + MD5Update(&md5, passphrase, passphrase_len); + MD5Final(keymat, &md5); + MD5Init(&md5); + MD5Update(&md5, passphrase, passphrase_len); + MD5Update(&md5, keymat, 16); + MD5Final(keymat + 16, &md5); + } +#endif /* 1 */ + /* Set the key to the cipher */ silc_cipher_set_key(aes, keymat, sizeof(keymat) * 8); @@ -1534,11 +1708,19 @@ bool silc_pkcs_load_private_key(const char *filename, silc_hmac_update(sha1hmac, data, len - mac_len); silc_hmac_final(sha1hmac, tmp, NULL); if (memcmp(tmp, data + (len - mac_len), mac_len)) { +#if 1 + /* Old support */ + if (!oldsupport) { + oldsupport = TRUE; + goto olds; + } +#endif + SILC_LOG_DEBUG(("Integrity check for private key failed")); memset(keymat, 0, sizeof(keymat)); memset(tmp, 0, sizeof(tmp)); silc_hmac_free(sha1hmac); - silc_hash_free(md5); + silc_hash_free(sha1); silc_cipher_free(aes); memset(old, 0, data_len); silc_free(old); @@ -1555,7 +1737,7 @@ bool silc_pkcs_load_private_key(const char *filename, memset(keymat, 0, sizeof(keymat)); memset(tmp, 0, sizeof(tmp)); silc_hmac_free(sha1hmac); - silc_hash_free(md5); + silc_hash_free(sha1); silc_cipher_free(aes); memset(old, 0, data_len); silc_free(old); @@ -1568,7 +1750,7 @@ bool silc_pkcs_load_private_key(const char *filename, memset(keymat, 0, sizeof(keymat)); memset(tmp, 0, sizeof(tmp)); silc_hmac_free(sha1hmac); - silc_hash_free(md5); + silc_hash_free(sha1); silc_cipher_free(aes); /* Now decode the actual private key */ @@ -1578,6 +1760,13 @@ bool silc_pkcs_load_private_key(const char *filename, return FALSE; } +#if 1 + /* Old support */ + if (oldsupport) + silc_pkcs_save_private_key((char *)filename, *private_key, + passphrase, passphrase_len, encoding); +#endif + memset(old, 0, data_len); silc_free(old); return TRUE;