X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilccore%2Fsilcauth.c;h=b98f36e84ae7d7e5aa5d42383ad2483b5dc71308;hb=40f8443d8d3a6577336ee66d18e04d9ac4d956bb;hp=cab3ae998f2c09306bfb49d399b62708d991ca35;hpb=8bf7b88c801ed119cc67664b0ffb22617125e626;p=silc.git diff --git a/lib/silccore/silcauth.c b/lib/silccore/silcauth.c index cab3ae99..b98f36e8 100644 --- a/lib/silccore/silcauth.c +++ b/lib/silccore/silcauth.c @@ -4,12 +4,11 @@ Author: Pekka Riikonen - Copyright (C) 2001 - 2002 Pekka Riikonen + Copyright (C) 2001 - 2005 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,7 +18,7 @@ */ /* $Id$ */ -#include "silcincludes.h" +#include "silc.h" #include "silcauth.h" /****************************************************************************** @@ -68,7 +67,14 @@ SilcAuthPayload silc_auth_payload_parse(const unsigned char *data, return NULL; } - if (newp->len != buffer.len) { + if (newp->len != silc_buffer_len(&buffer) || + newp->random_len + newp->auth_len > silc_buffer_len(&buffer) - 8) { + silc_auth_payload_free(newp); + return NULL; + } + + /* Authentication data must be provided */ + if (newp->auth_len < 1) { silc_auth_payload_free(newp); return NULL; } @@ -157,13 +163,24 @@ SilcAuthMethod silc_auth_get_method(SilcAuthPayload payload) return payload->auth_method; } +/* Get the public data from the auth payload. */ + +unsigned char *silc_auth_get_public_data(SilcAuthPayload payload, + SilcUInt32 *pubdata_len) +{ + if (pubdata_len) + *pubdata_len = (SilcUInt32)payload->random_len; + + return payload->random_data; +} + /* Get the authentication data. If this is passphrase it is UTF-8 encoded. */ unsigned char *silc_auth_get_data(SilcAuthPayload payload, SilcUInt32 *auth_len) { if (auth_len) - *auth_len = payload->auth_len; + *auth_len = (SilcUInt32)payload->auth_len; return payload->auth_data; } @@ -179,46 +196,37 @@ unsigned char *silc_auth_get_data(SilcAuthPayload payload, static unsigned char * silc_auth_public_key_encode_data(SilcPublicKey public_key, - const unsigned char *random, + const unsigned char *randomdata, SilcUInt32 random_len, const void *id, SilcIdType type, SilcUInt32 *ret_len) { SilcBuffer buf; - unsigned char *pk, *id_data, *ret; + unsigned char *pk, id_data[32], *ret; SilcUInt32 pk_len, id_len; pk = silc_pkcs_public_key_encode(public_key, &pk_len); if (!pk) return NULL; - id_data = silc_id_id2str(id, type); - if (!id_data) { + if (!silc_id_id2str(id, type, id_data, sizeof(id_data), &id_len)) { silc_free(pk); return NULL; } - id_len = silc_id_get_len(id, type); buf = silc_buffer_alloc_size(random_len + id_len + pk_len); if (!buf) { silc_free(pk); - silc_free(id_data); return NULL; } silc_buffer_format(buf, - SILC_STR_UI_XNSTRING(random, random_len), + SILC_STR_UI_XNSTRING(randomdata, random_len), SILC_STR_UI_XNSTRING(id_data, id_len), SILC_STR_UI_XNSTRING(pk, pk_len), SILC_STR_END); - ret = silc_memdup(buf->data, buf->len); - if (!ret) - return NULL; - - if (ret_len) - *ret_len = buf->len; + ret = silc_buffer_steal(buf, ret_len); silc_buffer_free(buf); - silc_free(id_data); silc_free(pk); return ret; @@ -233,8 +241,40 @@ SilcBuffer silc_auth_public_key_auth_generate(SilcPublicKey public_key, SilcRng rng, SilcHash hash, const void *id, SilcIdType type) { - unsigned char *random; - unsigned char auth_data[1024]; + unsigned char *randomdata; + SilcBuffer buf; + + /* Get 256 bytes of random data */ + if (rng) + randomdata = silc_rng_get_rn_data(rng, 256); + else + randomdata = silc_rng_global_get_rn_data(256); + if (!randomdata) + return NULL; + + buf = silc_auth_public_key_auth_generate_wpub(public_key, private_key, + randomdata, 256, hash, + id, type); + + memset(randomdata, 0, 256); + silc_free(randomdata); + + return buf; +} + +/* Generates Authentication Payload with authentication data. This is used + to do public key based authentication. This generates the random data + and the actual authentication data. Returns NULL on error. */ + +SilcBuffer +silc_auth_public_key_auth_generate_wpub(SilcPublicKey public_key, + SilcPrivateKey private_key, + const unsigned char *pubdata, + SilcUInt32 pubdata_len, + SilcHash hash, + const void *id, SilcIdType type) +{ + unsigned char auth_data[2048 + 1]; SilcUInt32 auth_len; unsigned char *tmp; SilcUInt32 tmp_len; @@ -243,22 +283,14 @@ SilcBuffer silc_auth_public_key_auth_generate(SilcPublicKey public_key, SILC_LOG_DEBUG(("Generating Authentication Payload with data")); - /* Get 256 bytes of random data */ - if (rng) - random = silc_rng_get_rn_data(rng, 256); - else - random = silc_rng_global_get_rn_data(256); - if (!random) - return NULL; - /* Encode the auth data */ - tmp = silc_auth_public_key_encode_data(public_key, random, 256, id, type, - &tmp_len); + tmp = silc_auth_public_key_encode_data(public_key, pubdata, pubdata_len, id, + type, &tmp_len); if (!tmp) return NULL; /* Allocate PKCS object */ - if (!silc_pkcs_alloc(public_key->name, &pkcs)) { + if (!silc_pkcs_alloc(private_key->name, SILC_PKCS_SILC, &pkcs)) { memset(tmp, 0, tmp_len); silc_free(tmp); return NULL; @@ -267,25 +299,22 @@ SilcBuffer silc_auth_public_key_auth_generate(SilcPublicKey public_key, silc_pkcs_private_key_set(pkcs, private_key); /* Compute the hash and the signature. */ - if (!silc_pkcs_sign_with_hash(pkcs, hash, tmp, tmp_len, auth_data, + if (silc_pkcs_get_key_len(pkcs) / 8 > sizeof(auth_data) - 1 || + !silc_pkcs_sign_with_hash(pkcs, hash, tmp, tmp_len, auth_data, &auth_len)) { - memset(random, 0, 256); memset(tmp, 0, tmp_len); silc_free(tmp); - silc_free(random); silc_pkcs_free(pkcs); return NULL; } /* Encode Authentication Payload */ - buf = silc_auth_payload_encode(SILC_AUTH_PUBLIC_KEY, random, 256, + buf = silc_auth_payload_encode(SILC_AUTH_PUBLIC_KEY, pubdata, pubdata_len, auth_data, auth_len); memset(tmp, 0, tmp_len); memset(auth_data, 0, sizeof(auth_data)); - memset(random, 0, 256); silc_free(tmp); - silc_free(random); silc_pkcs_free(pkcs); return buf; @@ -294,9 +323,10 @@ SilcBuffer silc_auth_public_key_auth_generate(SilcPublicKey public_key, /* Verifies the authentication data. Returns TRUE if authentication was successful. */ -bool silc_auth_public_key_auth_verify(SilcAuthPayload payload, - SilcPublicKey public_key, SilcHash hash, - const void *id, SilcIdType type) +SilcBool silc_auth_public_key_auth_verify(SilcAuthPayload payload, + SilcPublicKey public_key, + SilcHash hash, + const void *id, SilcIdType type) { unsigned char *tmp; SilcUInt32 tmp_len; @@ -314,7 +344,7 @@ bool silc_auth_public_key_auth_verify(SilcAuthPayload payload, } /* Allocate PKCS object */ - if (!silc_pkcs_alloc(public_key->name, &pkcs)) { + if (!silc_pkcs_alloc(public_key->name, SILC_PKCS_SILC, &pkcs)) { memset(tmp, 0, tmp_len); silc_free(tmp); return FALSE; @@ -343,11 +373,11 @@ bool silc_auth_public_key_auth_verify(SilcAuthPayload payload, /* Same as above but the payload is not parsed yet. This will parse it. */ -bool silc_auth_public_key_auth_verify_data(const unsigned char *payload, - SilcUInt32 payload_len, - SilcPublicKey public_key, - SilcHash hash, - const void *id, SilcIdType type) +SilcBool silc_auth_public_key_auth_verify_data(const unsigned char *payload, + SilcUInt32 payload_len, + SilcPublicKey public_key, + SilcHash hash, + const void *id, SilcIdType type) { SilcAuthPayload auth_payload; int ret; @@ -373,13 +403,13 @@ bool silc_auth_public_key_auth_verify_data(const unsigned char *payload, authentication then the `auth_data' is the SilcPublicKey and the `auth_data_len' is ignored. */ -bool silc_auth_verify(SilcAuthPayload payload, SilcAuthMethod auth_method, - const void *auth_data, SilcUInt32 auth_data_len, - SilcHash hash, const void *id, SilcIdType type) +SilcBool silc_auth_verify(SilcAuthPayload payload, SilcAuthMethod auth_method, + const void *auth_data, SilcUInt32 auth_data_len, + SilcHash hash, const void *id, SilcIdType type) { SILC_LOG_DEBUG(("Verifying authentication")); - if (auth_method != payload->auth_method) + if (!payload || auth_method != payload->auth_method) return FALSE; switch (payload->auth_method) { @@ -391,15 +421,12 @@ bool silc_auth_verify(SilcAuthPayload payload, SilcAuthMethod auth_method, case SILC_AUTH_PASSWORD: /* Passphrase based authentication. The `pkcs', `hash', `id' and `type' arguments are not needed. */ - /* Carefully check that the auth_data field of the payload is not empty - (len=0), which seems to be a legal packet but would crash the - application. Maybe such packet should be dropped. -Johnny 2002/14/4 */ - if ((payload->auth_len == 0) || !auth_data) - break; - /* if lengths mismatch, avoid comparing unallocated memory locations */ - if (payload->auth_len != auth_data_len) + /* Sanity checks */ + if ((payload->auth_len == 0) || !auth_data || + payload->auth_len != auth_data_len) break; + if (!memcmp(payload->auth_data, auth_data, auth_data_len)) { SILC_LOG_DEBUG(("Passphrase Authentication successful")); return TRUE; @@ -423,14 +450,15 @@ bool silc_auth_verify(SilcAuthPayload payload, SilcAuthMethod auth_method, /* Same as above but parses the authentication payload before verify. */ -bool silc_auth_verify_data(const unsigned char *payload, - SilcUInt32 payload_len, - SilcAuthMethod auth_method, const void *auth_data, - SilcUInt32 auth_data_len, SilcHash hash, - const void *id, SilcIdType type) +SilcBool silc_auth_verify_data(const unsigned char *payload, + SilcUInt32 payload_len, + SilcAuthMethod auth_method, + const void *auth_data, + SilcUInt32 auth_data_len, SilcHash hash, + const void *id, SilcIdType type) { SilcAuthPayload auth_payload; - bool ret; + SilcBool ret; auth_payload = silc_auth_payload_parse(payload, payload_len); if (!auth_payload || (auth_payload->auth_len == 0)) @@ -480,7 +508,7 @@ silc_key_agreement_payload_parse(const unsigned char *payload, &newp->hostname_len), SILC_STR_UI_INT(&newp->port), SILC_STR_END); - if (ret == -1) { + if (ret == -1 || newp->hostname_len > silc_buffer_len(&buffer) - 6) { silc_free(newp); return NULL; }