X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilccore%2Fsilcauth.c;h=b98f36e84ae7d7e5aa5d42383ad2483b5dc71308;hb=40f8443d8d3a6577336ee66d18e04d9ac4d956bb;hp=c93f02df1e2b0213a4dce16c2b90a79441cfc373;hpb=cdedc07c65bab8467f6f5b1ef4b38982c2c77571;p=silc.git diff --git a/lib/silccore/silcauth.c b/lib/silccore/silcauth.c index c93f02df..b98f36e8 100644 --- a/lib/silccore/silcauth.c +++ b/lib/silccore/silcauth.c @@ -1,10 +1,10 @@ /* - silcauth.c + silcauth.c 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 @@ -18,10 +18,8 @@ */ /* $Id$ */ -#include "silcincludes.h" +#include "silc.h" #include "silcauth.h" -#include "silcchannel_i.h" -#include "silcprivate_i.h" /****************************************************************************** @@ -69,8 +67,8 @@ SilcAuthPayload silc_auth_payload_parse(const unsigned char *data, return NULL; } - if (newp->len != buffer.len || - newp->random_len + newp->auth_len > buffer.len - 8) { + 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; } @@ -165,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; } @@ -192,24 +201,21 @@ silc_auth_public_key_encode_data(SilcPublicKey public_key, 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, @@ -218,16 +224,9 @@ silc_auth_public_key_encode_data(SilcPublicKey public_key, SILC_STR_UI_XNSTRING(pk, pk_len), SILC_STR_END); - ret = silc_memdup(buf->data, buf->len); - if (!ret) - return NULL; + ret = silc_buffer_steal(buf, ret_len); - if (ret_len) - *ret_len = buf->len; - - silc_buffer_clear(buf); silc_buffer_free(buf); - silc_free(id_data); silc_free(pk); return ret; @@ -243,14 +242,7 @@ SilcBuffer silc_auth_public_key_auth_generate(SilcPublicKey public_key, const void *id, SilcIdType type) { unsigned char *randomdata; - unsigned char auth_data[2048]; - SilcUInt32 auth_len; - unsigned char *tmp; - SilcUInt32 tmp_len; SilcBuffer buf; - SilcPKCS pkcs; - - SILC_LOG_DEBUG(("Generating Authentication Payload with data")); /* Get 256 bytes of random data */ if (rng) @@ -260,14 +252,45 @@ SilcBuffer silc_auth_public_key_auth_generate(SilcPublicKey public_key, 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; + SilcBuffer buf; + SilcPKCS pkcs; + + SILC_LOG_DEBUG(("Generating Authentication Payload with data")); + /* Encode the auth data */ - tmp = silc_auth_public_key_encode_data(public_key, randomdata, 256, id, + 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(private_key->name, &pkcs)) { + if (!silc_pkcs_alloc(private_key->name, SILC_PKCS_SILC, &pkcs)) { memset(tmp, 0, tmp_len); silc_free(tmp); return NULL; @@ -279,23 +302,19 @@ SilcBuffer silc_auth_public_key_auth_generate(SilcPublicKey public_key, 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(randomdata, 0, 256); memset(tmp, 0, tmp_len); silc_free(tmp); - silc_free(randomdata); silc_pkcs_free(pkcs); return NULL; } /* Encode Authentication Payload */ - buf = silc_auth_payload_encode(SILC_AUTH_PUBLIC_KEY, randomdata, 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(randomdata, 0, 256); silc_free(tmp); - silc_free(randomdata); silc_pkcs_free(pkcs); return buf; @@ -304,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; @@ -324,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; @@ -353,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; @@ -383,9 +403,9 @@ 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")); @@ -430,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)) @@ -487,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; } @@ -540,319 +561,3 @@ SilcUInt32 silc_key_agreement_get_port(SilcKeyAgreementPayload payload) { return payload->port; } - -/****************************************************************************** - - SILC_MESSAGE_FLAG_SIGNED Payload - -******************************************************************************/ - -/* The SILC_MESSAGE_FLAG_SIGNED Payload */ -struct SilcSignedPayloadStruct { - SilcUInt16 pk_len; - SilcUInt16 pk_type; - SilcUInt16 sign_len; - unsigned char *pk_data; - unsigned char *sign_data; -}; - -/* Encodes the data to be signed to SILC_MESSAGE_FLAG_SIGNED Payload */ - -static SilcBuffer -silc_signed_payload_encode_data(const unsigned char *message_payload, - SilcUInt32 message_payload_len, - unsigned char *pk, - SilcUInt32 pk_len, SilcUInt32 pk_type) -{ - SilcBuffer sign; - - sign = silc_buffer_alloc_size(message_payload_len + 4 + pk_len); - if (!sign) - return NULL; - - silc_buffer_format(sign, - SILC_STR_UI_XNSTRING(message_payload, - message_payload_len), - SILC_STR_UI_SHORT(pk_len), - SILC_STR_UI_SHORT(pk_type), - SILC_STR_END); - - if (pk && pk_len) { - silc_buffer_pull(sign, message_payload_len + 4); - silc_buffer_format(sign, - SILC_STR_UI_XNSTRING(pk, pk_len), - SILC_STR_END); - silc_buffer_push(sign, message_payload_len + 4); - } - - return sign; -} - -/* Parses the SILC_MESSAGE_FLAG_SIGNED Payload */ - -SilcSignedPayload silc_signed_payload_parse(const unsigned char *data, - SilcUInt32 data_len) -{ - SilcSignedPayload sig; - SilcBufferStruct buffer; - int ret; - - SILC_LOG_DEBUG(("Parsing SILC_MESSAGE_FLAG_SIGNED Payload")); - - silc_buffer_set(&buffer, (unsigned char *)data, data_len); - sig = silc_calloc(1, sizeof(*sig)); - if (!sig) - return NULL; - - /* Parse the payload */ - ret = silc_buffer_unformat(&buffer, - SILC_STR_UI_SHORT(&sig->pk_len), - SILC_STR_UI_SHORT(&sig->pk_type), - SILC_STR_END); - if (ret == -1 || sig->pk_len > data_len - 4) { - silc_signed_payload_free(sig); - return NULL; - } - - silc_buffer_pull(&buffer, 4); - ret = silc_buffer_unformat(&buffer, - SILC_STR_UI_XNSTRING_ALLOC(&sig->pk_data, - sig->pk_len), - SILC_STR_UI16_NSTRING_ALLOC(&sig->sign_data, - &sig->sign_len), - SILC_STR_END); - if (ret == -1) { - silc_signed_payload_free(sig); - return NULL; - } - silc_buffer_push(&buffer, 4); - - /* Signature must be provided */ - if (sig->sign_len < 1) { - silc_signed_payload_free(sig); - return NULL; - } - - return sig; -} - -/* Encodes the SILC_MESSAGE_FLAG_SIGNED Payload and computes the digital - signature. */ - -SilcBuffer silc_signed_payload_encode(const unsigned char *message_payload, - SilcUInt32 message_payload_len, - SilcPublicKey public_key, - SilcPrivateKey private_key, - SilcHash hash, - bool include_public_key) -{ - SilcBuffer buffer, sign; - SilcPKCS pkcs; - unsigned char auth_data[2048]; - SilcUInt32 auth_len; - unsigned char *pk = NULL; - SilcUInt32 pk_len = 0; - SilcUInt16 pk_type; - - if (!message_payload || !message_payload_len || !private_key || !hash) - return NULL; - if (include_public_key && !public_key) - return NULL; - - if (include_public_key) - pk = silc_pkcs_public_key_encode(public_key, &pk_len); - - /* Now we support only SILC style public key */ - pk_type = SILC_SKE_PK_TYPE_SILC; - - /* Encode the data to be signed */ - sign = silc_signed_payload_encode_data(message_payload, - message_payload_len, - pk, pk_len, pk_type); - if (!sign) { - silc_free(pk); - return NULL; - } - - /* Sign the buffer */ - - /* Allocate PKCS object */ - if (!silc_pkcs_alloc(private_key->name, &pkcs)) { - silc_buffer_clear(sign); - silc_buffer_free(sign); - silc_free(pk); - return NULL; - } - silc_pkcs_private_key_set(pkcs, private_key); - - /* Compute the hash and the signature. */ - if (silc_pkcs_get_key_len(pkcs) / 8 > sizeof(auth_data) - 1 || - !silc_pkcs_sign_with_hash(pkcs, hash, sign->data, sign->len, auth_data, - &auth_len)) { - silc_buffer_clear(sign); - silc_buffer_free(sign); - silc_pkcs_free(pkcs); - silc_free(pk); - return NULL; - } - - /* Encode the SILC_MESSAGE_FLAG_SIGNED Payload */ - - buffer = silc_buffer_alloc_size(4 + pk_len + 2 + auth_len); - if (!buffer) { - silc_buffer_clear(sign); - silc_buffer_free(sign); - silc_pkcs_free(pkcs); - memset(auth_data, 0, sizeof(auth_data)); - silc_free(pk); - return NULL; - } - - silc_buffer_format(sign, - SILC_STR_UI_SHORT(pk_len), - SILC_STR_UI_SHORT(pk_type), - SILC_STR_END); - - if (pk_len && pk) { - silc_buffer_pull(sign, 4); - silc_buffer_format(sign, - SILC_STR_UI_XNSTRING(pk, pk_len), - SILC_STR_END); - silc_buffer_push(sign, 4); - } - - silc_buffer_pull(sign, 4 + pk_len); - silc_buffer_format(sign, - SILC_STR_UI_SHORT(auth_len), - SILC_STR_UI_XNSTRING(auth_data, auth_len), - SILC_STR_END); - silc_buffer_push(sign, 4 + pk_len); - - memset(auth_data, 0, sizeof(auth_data)); - silc_pkcs_free(pkcs); - silc_buffer_clear(sign); - silc_buffer_free(sign); - silc_free(pk); - - return buffer; -} - -/* Free the payload */ - -void silc_signed_payload_free(SilcSignedPayload sig) -{ - if (sig) { - memset(sig->sign_data, 0, sig->sign_len); - silc_free(sig->sign_data); - silc_free(sig->pk_data); - silc_free(sig); - } -} - -/* Verify the signature in SILC_MESSAGE_FLAG_SIGNED Payload */ - -int silc_signed_payload_verify(SilcSignedPayload sig, - bool channel_message, - void *message_payload, - SilcPublicKey remote_public_key, - SilcHash hash) -{ - int ret = SILC_AUTH_FAILED; -#if 0 - SilcBuffer sign; - SilcPKCS pkcs; - - if (!sig || !remote_public_key || !hash) - return ret; - - /* Generate the signature verification data */ - if (channel_message) { - SilcChannelMessagePayload chm = - (SilcChannelMessagePayload)message_payload; - SilcBuffer tmp; - - /* Encode Channel Message Payload */ - tmp = silc_buffer_alloc_size(6 + chm->data_len + chm->pad_len + - chm->iv_len); - silc_buffer_format(tmp, - SILC_STR_UI_SHORT(chm->flags), - SILC_STR_UI_SHORT(chm->data_len), - SILC_STR_UI_XNSTRING(chm->data, chm->data_len), - SILC_STR_UI_SHORT(chm->pad_len), - SILC_STR_UI_XNSTRING(chm->pad, chm->pad_len), - SILC_STR_UI_XNSTRING(chm->iv, chm->iv_len), - SILC_STR_END); - - sign = silc_signed_payload_encode_data(tmp->data, tmp->len, - sig->pk_data, sig->pk_len, - sig->pk_type); - silc_buffer_clear(tmp); - silc_buffer_free(tmp); - } else { - SilcPrivateMessagePayload prm = - (SilcPrivateMessagePayload)message_payload; - SilcBuffer tmp; - - /* Encode Private Message Payload */ - tmp = silc_buffer_alloc_size(4 + prm->data_len + - SILC_PRIVATE_MESSAGE_PAD(4 + prm->data_len)); - silc_buffer_format(tmp, - SILC_STR_UI_SHORT(prm->flags), - SILC_STR_UI_SHORT(prm->message_len), - SILC_STR_UI_XNSTRING(prm->message, prm->message_len), - SILC_STR_END); - - sign = silc_signed_payload_encode_data(tmp->data, tmp->len, - sig->pk_data, sig->pk_len, - sig->pk_type); - silc_buffer_clear(tmp); - silc_buffer_free(tmp); - } - - if (!sign) - return ret; - - /* Allocate PKCS object */ - if (!silc_pkcs_alloc(remote_public_key->name, &pkcs)) { - silc_buffer_clear(sign); - silc_buffer_free(sign); - return ret; - } - silc_pkcs_public_key_set(pkcs, remote_public_key); - - /* Verify the authentication data */ - if (!silc_pkcs_verify_with_hash(pkcs, hash, payload->sign_data - payload->sign_len, - sign->data, sign->len)) { - - silc_buffer_clear(sign); - silc_buffer_free(sign); - silc_pkcs_free(pkcs); - SILC_LOG_DEBUG(("Signature verification failed")); - return ret; - } - - ret = SILC_AUTH_OK; - - silc_buffer_clear(sign); - silc_buffer_free(sign); - silc_pkcs_free(pkcs); - - SILC_LOG_DEBUG(("Signature verification successful")); - -#endif - return ret; -} - -/* Return the public key from the payload */ - -SilcPublicKey silc_signed_payload_get_public_key(SilcSignedPayload sig) -{ - SilcPublicKey pk; - - if (!sig->pk_data || !silc_pkcs_public_key_decode(sig->pk_data, - sig->pk_len, &pk)) - return NULL; - - return pk; -}