From 0e112fbe2a39a89db41e41ccd87cd14e572d486f Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Sun, 8 Jul 2007 17:30:24 +0000 Subject: [PATCH] SILC PKCS API was changed async. Added SilcStack support. --- lib/silccore/silcauth.c | 350 +++++++++++++++---------- lib/silccore/silcauth.h | 212 ++++++++++----- lib/silccore/silcmessage.c | 511 ++++++++++++++++++++++--------------- lib/silccore/silcmessage.h | 119 +++++---- 4 files changed, 750 insertions(+), 442 deletions(-) diff --git a/lib/silccore/silcauth.c b/lib/silccore/silcauth.c index da2a502f..5082162e 100644 --- a/lib/silccore/silcauth.c +++ b/lib/silccore/silcauth.c @@ -29,17 +29,19 @@ /* Authentication Payload structure */ struct SilcAuthPayloadStruct { + SilcStack stack; + unsigned char *random_data; + unsigned char *auth_data; + SilcUInt16 auth_len; SilcUInt16 len; SilcUInt16 auth_method; SilcUInt16 random_len; - unsigned char *random_data; - SilcUInt16 auth_len; - unsigned char *auth_data; }; /* Parses and returns Authentication Payload */ -SilcAuthPayload silc_auth_payload_parse(const unsigned char *data, +SilcAuthPayload silc_auth_payload_parse(SilcStack stack, + const unsigned char *data, SilcUInt32 data_len) { SilcBufferStruct buffer; @@ -49,21 +51,29 @@ SilcAuthPayload silc_auth_payload_parse(const unsigned char *data, SILC_LOG_DEBUG(("Parsing Authentication Payload")); silc_buffer_set(&buffer, (unsigned char *)data, data_len); - newp = silc_calloc(1, sizeof(*newp)); - if (!newp) + + if (stack) + stack = silc_stack_alloc(0, stack); + + newp = silc_scalloc(stack, 1, sizeof(*newp)); + if (!newp) { + silc_stack_free(stack); return NULL; + } + newp->stack = stack; /* Parse the payload */ - ret = silc_buffer_unformat(&buffer, - SILC_STR_UI_SHORT(&newp->len), - SILC_STR_UI_SHORT(&newp->auth_method), - SILC_STR_UI16_NSTRING_ALLOC(&newp->random_data, - &newp->random_len), - SILC_STR_UI16_NSTRING_ALLOC(&newp->auth_data, - &newp->auth_len), - SILC_STR_END); + ret = silc_buffer_sunformat(stack, &buffer, + SILC_STR_UI_SHORT(&newp->len), + SILC_STR_UI_SHORT(&newp->auth_method), + SILC_STR_UI16_NSTRING_ALLOC(&newp->random_data, + &newp->random_len), + SILC_STR_UI16_NSTRING_ALLOC(&newp->auth_data, + &newp->auth_len), + SILC_STR_END); if (ret == -1) { - silc_free(newp); + silc_sfree(stack, newp); + silc_stack_free(stack); return NULL; } @@ -96,7 +106,8 @@ SilcAuthPayload silc_auth_payload_parse(const unsigned char *data, /* Encodes authentication payload into buffer and returns it */ -SilcBuffer silc_auth_payload_encode(SilcAuthMethod method, +SilcBuffer silc_auth_payload_encode(SilcStack stack, + SilcAuthMethod method, const unsigned char *random_data, SilcUInt16 random_len, const unsigned char *auth_data, @@ -114,28 +125,28 @@ SilcBuffer silc_auth_payload_encode(SilcAuthMethod method, autf8_len = silc_utf8_encoded_len(auth_data, auth_len, 0); if (!autf8_len) return NULL; - autf8 = silc_calloc(autf8_len, sizeof(*autf8)); + autf8 = silc_scalloc(stack, autf8_len, sizeof(*autf8)); auth_len = silc_utf8_encode(auth_data, auth_len, 0, autf8, autf8_len); auth_data = (const unsigned char *)autf8; } len = 2 + 2 + 2 + random_len + 2 + auth_len; - buffer = silc_buffer_alloc_size(len); + buffer = silc_buffer_salloc_size(stack, len); if (!buffer) { - silc_free(autf8); + silc_sfree(stack, autf8); return NULL; } - silc_buffer_format(buffer, - SILC_STR_UI_SHORT(len), - SILC_STR_UI_SHORT(method), - SILC_STR_UI_SHORT(random_len), - SILC_STR_UI_XNSTRING(random_data, random_len), - SILC_STR_UI_SHORT(auth_len), - SILC_STR_UI_XNSTRING(auth_data, auth_len), - SILC_STR_END); + silc_buffer_sformat(stack, buffer, + SILC_STR_UI_SHORT(len), + SILC_STR_UI_SHORT(method), + SILC_STR_UI_SHORT(random_len), + SILC_STR_UI_XNSTRING(random_data, random_len), + SILC_STR_UI_SHORT(auth_len), + SILC_STR_UI_XNSTRING(auth_data, auth_len), + SILC_STR_END); - silc_free(autf8); + silc_sfree(stack, autf8); return buffer; } @@ -144,15 +155,19 @@ SilcBuffer silc_auth_payload_encode(SilcAuthMethod method, void silc_auth_payload_free(SilcAuthPayload payload) { if (payload) { + SilcStack stack = payload->stack; + if (payload->random_data) { memset(payload->random_data, 0, payload->random_len); - silc_free(payload->random_data); + silc_sfree(stack, payload->random_data); } if (payload->auth_data) { memset(payload->auth_data, 0, payload->auth_len); - silc_free(payload->auth_data); + silc_sfree(stack, payload->auth_data); } - silc_free(payload); + + silc_sfree(stack, payload); + silc_stack_free(stack); } } @@ -195,7 +210,8 @@ unsigned char *silc_auth_get_data(SilcAuthPayload payload, dictates. */ static unsigned char * -silc_auth_public_key_encode_data(SilcPublicKey public_key, +silc_auth_public_key_encode_data(SilcStack stack, + SilcPublicKey public_key, const unsigned char *randomdata, SilcUInt32 random_len, const void *id, SilcIdType type, SilcUInt32 *ret_len) @@ -204,7 +220,7 @@ silc_auth_public_key_encode_data(SilcPublicKey public_key, unsigned char *pk, id_data[32], *ret; SilcUInt32 pk_len, id_len; - pk = silc_pkcs_public_key_encode(public_key, &pk_len); + pk = silc_pkcs_public_key_encode(stack, public_key, &pk_len); if (!pk) return NULL; @@ -213,163 +229,223 @@ silc_auth_public_key_encode_data(SilcPublicKey public_key, return NULL; } - buf = silc_buffer_alloc_size(random_len + id_len + pk_len); + buf = silc_buffer_salloc_size(stack, random_len + id_len + pk_len); if (!buf) { silc_free(pk); return NULL; } - silc_buffer_format(buf, - 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); + silc_buffer_sformat(stack, buf, + 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_buffer_steal(buf, ret_len); - silc_buffer_free(buf); - silc_free(pk); + silc_buffer_sfree(stack, buf); + silc_sfree(stack, pk); return ret; } +typedef struct { + SilcStack stack; + unsigned char *pubdata; + SilcUInt32 pubdata_len; + SilcAuthGenerated generated; + void *context; +} *SilcAuthGenerateContext; + +/* Signature callback */ + +static void +silc_auth_public_key_auth_generate_cb(SilcBool success, + const unsigned char *signature, + SilcUInt32 signature_len, + void *context) +{ + SilcAuthGenerateContext a = context; + SilcStack stack = a->stack; + SilcBuffer buf; + + if (!success) { + a->generated(NULL, context); + silc_sfree(stack, a->pubdata); + silc_sfree(stack, a); + silc_stack_free(stack); + return; + } + + /* Encode Authentication Payload */ + buf = silc_auth_payload_encode(stack, SILC_AUTH_PUBLIC_KEY, a->pubdata, + a->pubdata_len, signature, signature_len); + + a->generated(buf, context); + + silc_buffer_sfree(stack, buf); + silc_sfree(stack, a->pubdata); + silc_sfree(stack, a); + silc_stack_free(stack); +} + /* 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(SilcPublicKey public_key, - SilcPrivateKey private_key, - SilcRng rng, SilcHash hash, - const void *id, SilcIdType type) +SilcAsyncOperation +silc_auth_public_key_auth_generate(SilcPublicKey public_key, + SilcPrivateKey private_key, + SilcRng rng, SilcHash hash, + const void *id, SilcIdType type, + SilcAuthGenerated generated, + void *context) { - unsigned char *randomdata; - SilcBuffer buf; + unsigned char randomdata[256]; - /* Get 256 bytes of random data */ + /* Get random data */ if (rng) - randomdata = silc_rng_get_rn_data(rng, 256); + silc_rng_get_rn_data(rng, sizeof(randomdata), randomdata, + sizeof(randomdata)); 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); + silc_rng_global_get_rn_data(rng, sizeof(randomdata), randomdata, + sizeof(randomdata)); - return buf; + return silc_auth_public_key_auth_generate_wpub(public_key, private_key, + randomdata, sizeof(randomdata), + hash, id, type, generated, + context); } /* 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 +SilcAsyncOperation 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) + const void *id, SilcIdType type, + SilcAuthGenerated generated, + void *context) { - unsigned char auth_data[2048 + 1]; - SilcUInt32 auth_len; + SilcAuthGenerateContext a; + SilcAsyncOperation op; unsigned char *tmp; SilcUInt32 tmp_len; - SilcBuffer buf; + SilcStack stack; SILC_LOG_DEBUG(("Generating Authentication Payload with data")); + /* We use the Crypto Toolkit's stack since we're doing crypto */ + stack = silc_stack_alloc(2048, silc_crypto_stack()); + + a = silc_scalloc(stack, 1, sizeof(*a)); + if (!a) { + generated(NULL, context); + return NULL; + } + a->stack = stack; + /* Encode the auth data */ - tmp = silc_auth_public_key_encode_data(public_key, pubdata, pubdata_len, id, - type, &tmp_len); - if (!tmp) + tmp = silc_auth_public_key_encode_data(stack, public_key, pubdata, + pubdata_len, id, type, &tmp_len); + if (!tmp) { + silc_sfree(stack, a); + silc_stack_free(stack); + generated(NULL, context); return NULL; + } - /* Compute the hash and the signature. */ - if (!silc_pkcs_sign(private_key, tmp, tmp_len, auth_data, - sizeof(auth_data) - 1, &auth_len, TRUE, hash)) { + a->pubdata = silc_smemdup(stack, pubdata, pubdata_len); + if (!a->pubdata) { memset(tmp, 0, tmp_len); - silc_free(tmp); + silc_sfree(stack, tmp); + silc_sfree(stack, a); + silc_stack_free(stack); + generated(NULL, context); return NULL; } - /* Encode Authentication Payload */ - buf = silc_auth_payload_encode(SILC_AUTH_PUBLIC_KEY, pubdata, pubdata_len, - auth_data, auth_len); + /* Compute the hash and the signature. */ + op = silc_pkcs_sign(private_key, tmp, tmp_len, TRUE, hash, + silc_auth_public_key_auth_generate_cb, a); memset(tmp, 0, tmp_len); - memset(auth_data, 0, sizeof(auth_data)); - silc_free(tmp); + silc_sfree(stack, tmp); - return buf; + return op; } -/* Verifies the authentication data. Returns TRUE if authentication was - successful. */ +/* Verifies the authentication data. */ -SilcBool silc_auth_public_key_auth_verify(SilcAuthPayload payload, - SilcPublicKey public_key, - SilcHash hash, - const void *id, SilcIdType type) +SilcAsyncOperation +silc_auth_public_key_auth_verify(SilcAuthPayload payload, + SilcPublicKey public_key, + SilcHash hash, + const void *id, + SilcIdType type, + SilcAuthResultCb result, + void *context) { + SilcAsyncOperation op; unsigned char *tmp; SilcUInt32 tmp_len; SILC_LOG_DEBUG(("Verifying authentication data")); /* Encode auth data */ - tmp = silc_auth_public_key_encode_data(public_key, payload->random_data, + tmp = silc_auth_public_key_encode_data(payload->stack, + public_key, payload->random_data, payload->random_len, id, type, &tmp_len); if (!tmp) { SILC_LOG_DEBUG(("Authentication failed")); - return FALSE; + result(FALSE, context); + return NULL; } /* Verify the authentication data */ - if (!silc_pkcs_verify(public_key, payload->auth_data, - payload->auth_len, tmp, tmp_len, hash)) { - - memset(tmp, 0, tmp_len); - silc_free(tmp); - SILC_LOG_DEBUG(("Authentication failed")); - return FALSE; - } + op = silc_pkcs_verify(public_key, payload->auth_data, + payload->auth_len, tmp, tmp_len, hash, + result, context); memset(tmp, 0, tmp_len); - silc_free(tmp); + silc_sfree(payload->stack, tmp); - SILC_LOG_DEBUG(("Authentication successful")); - - return TRUE; + return op; } /* Same as above but the payload is not parsed yet. This will parse it. */ -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) +SilcAsyncOperation +silc_auth_public_key_auth_verify_data(const unsigned char *payload, + SilcUInt32 payload_len, + SilcPublicKey public_key, + SilcHash hash, + const void *id, + SilcIdType type, + SilcAuthResultCb result, + void *context) { + SilcAsyncOperation op; SilcAuthPayload auth_payload; - int ret; - auth_payload = silc_auth_payload_parse(payload, payload_len); + auth_payload = silc_auth_payload_parse(silc_crypto_stack(), payload, + payload_len); if (!auth_payload) { SILC_LOG_DEBUG(("Authentication failed")); - return FALSE; + result(FALSE, context); + return NULL; } - ret = silc_auth_public_key_auth_verify(auth_payload, public_key, hash, - id, type); + op = silc_auth_public_key_auth_verify(auth_payload, public_key, hash, + id, type, result, context); silc_auth_payload_free(auth_payload); - return ret; + return op; } /* Verifies the authentication data directly from the Authentication @@ -379,20 +455,25 @@ SilcBool 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. */ -SilcBool silc_auth_verify(SilcAuthPayload payload, SilcAuthMethod auth_method, - const void *auth_data, SilcUInt32 auth_data_len, - SilcHash hash, const void *id, SilcIdType type) +SilcAsyncOperation +silc_auth_verify(SilcAuthPayload payload, SilcAuthMethod auth_method, + const void *auth_data, SilcUInt32 auth_data_len, + SilcHash hash, const void *id, SilcIdType type, + SilcAuthResultCb result, void *context) { SILC_LOG_DEBUG(("Verifying authentication")); - if (!payload || auth_method != payload->auth_method) - return FALSE; + if (!payload || auth_method != payload->auth_method) { + result(FALSE, context); + return NULL; + } switch (payload->auth_method) { case SILC_AUTH_NONE: /* No authentication */ SILC_LOG_DEBUG(("No authentication required")); - return TRUE; + result(TRUE, context); + return NULL; case SILC_AUTH_PASSWORD: /* Passphrase based authentication. The `pkcs', `hash', `id' and `type' @@ -405,14 +486,15 @@ SilcBool silc_auth_verify(SilcAuthPayload payload, SilcAuthMethod auth_method, if (!memcmp(payload->auth_data, auth_data, auth_data_len)) { SILC_LOG_DEBUG(("Passphrase Authentication successful")); - return TRUE; + result(TRUE, context); + return NULL; } break; case SILC_AUTH_PUBLIC_KEY: /* Public key based authentication */ return silc_auth_public_key_auth_verify(payload, (SilcPublicKey)auth_data, - hash, id, type); + hash, id, type, result, context); break; default: @@ -420,32 +502,38 @@ SilcBool silc_auth_verify(SilcAuthPayload payload, SilcAuthMethod auth_method, } SILC_LOG_DEBUG(("Authentication failed")); + result(FALSE, context); - return FALSE; + return NULL; } /* Same as above but parses the authentication payload before verify. */ -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) +SilcAsyncOperation +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, + SilcAuthResultCb result, void *context) { + SilcAsyncOperation op; SilcAuthPayload auth_payload; - SilcBool ret; - auth_payload = silc_auth_payload_parse(payload, payload_len); - if (!auth_payload || (auth_payload->auth_len == 0)) - return FALSE; + auth_payload = silc_auth_payload_parse(silc_crypto_stack(), payload, + payload_len); + if (!auth_payload || (auth_payload->auth_len == 0)) { + result(FALSE, context); + return NULL; + } - ret = silc_auth_verify(auth_payload, auth_method, auth_data, auth_data_len, - hash, id, type); + op = silc_auth_verify(auth_payload, auth_method, auth_data, auth_data_len, + hash, id, type, result, context); silc_auth_payload_free(auth_payload); - return ret; + return op; } /****************************************************************************** diff --git a/lib/silccore/silcauth.h b/lib/silccore/silcauth.h index 39b7c328..438c461c 100644 --- a/lib/silccore/silcauth.h +++ b/lib/silccore/silcauth.h @@ -97,23 +97,27 @@ typedef struct SilcAuthPayloadStruct *SilcAuthPayload; * * SYNOPSIS * - * SilcAuthPayload silc_auth_payload_parse(const unsigned char *data, + * SilcAuthPayload silc_auth_payload_parse(SilcStack stack, + * const unsigned char *data, * SilcUInt32 data_len); * * DESCRIPTION * * Parses and returns Authentication Payload. The `data' and the - * `data_len' are the raw payload buffer. + * `data_len' are the raw payload buffer. If `stack' is non-NULL the + * memory is allcoated from `stack'. * ***/ -SilcAuthPayload silc_auth_payload_parse(const unsigned char *data, +SilcAuthPayload silc_auth_payload_parse(SilcStack stack, + const unsigned char *data, SilcUInt32 data_len); /****f* silccore/SilcAuthAPI/silc_auth_payload_encode * * SYNOPSIS * - * SilcBuffer silc_auth_payload_encode(SilcAuthMethod method, + * SilcBuffer silc_auth_payload_encode(SilcStack stack, + * SilcAuthMethod method, * const unsigned char *random_data, * SilcUInt16 random_len, * const unsigned char *auth_data, @@ -128,8 +132,13 @@ SilcAuthPayload silc_auth_payload_parse(const unsigned char *data, * argument SHOULD be UTF-8 encoded, if not library will attempt to * encode it. * + * If `stack' is non-NULL the returned buffer is allocated from `stack'. + * This call consumes the `stack' so caller should push the stack before + * calling this function and then later pop it. + * ***/ -SilcBuffer silc_auth_payload_encode(SilcAuthMethod method, +SilcBuffer silc_auth_payload_encode(SilcStack stack, + SilcAuthMethod method, const unsigned char *random_data, SilcUInt16 random_len, const unsigned char *auth_data, @@ -194,23 +203,41 @@ unsigned char *silc_auth_get_public_data(SilcAuthPayload payload, unsigned char *silc_auth_get_data(SilcAuthPayload payload, SilcUInt32 *auth_len); +/****f* silccore/SilcAuthAPI/SilcAuthGenerated + * + * SYNOPSIS + * + * typedef void (*SilcAuthGenerated)(const SilcBuffer data, void *context); + * + * DESCRIPTION + * + * Callback of this type is given as argument to + * silc_auth_public_key_auth_generate and + * silc_auth_public_key_auth_generate_wpub to deliver the generated + * Authentication Payload. If `data' is NULL the generating failed. + * + ***/ +typedef void (*SilcAuthGenerated)(const SilcBuffer data, void *context); + /****f* silccore/SilcAuthAPI/silc_auth_public_key_auth_generate * * SYNOPSIS * - * SilcBuffer silc_auth_public_key_auth_generate(SilcPublicKey public_key, - * SilcPrivateKey private_key, - * SilcRng rng, - * SilcHash hash, - * const void *id, - * SilcIdType type); + * SilcAsyncOperation + * silc_auth_public_key_auth_generate(SilcPublicKey public_key, + * SilcPrivateKey private_key, + * SilcRng rng, + * SilcHash hash, + * const void *id, + * SilcIdType type, + * SilcAuthGenerated generated, + * void *context); * * DESCRIPTION * * 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 and the - * encoded Authentication Payload on success. + * and the actual authentication data. * * The `private_key' is used to sign the payload. The `public_key', the * and the `id' is encoded in the payload and signed. If the `rng' is @@ -218,24 +245,32 @@ unsigned char *silc_auth_get_data(SilcAuthPayload payload, * random number generator. Also random number is encoded in the * payload before signing it with `private_key'. * + * The `generated' is called to deliver the generated Authentication + * Payload. + * ***/ -SilcBuffer silc_auth_public_key_auth_generate(SilcPublicKey public_key, - SilcPrivateKey private_key, - SilcRng rng, SilcHash hash, - const void *id, SilcIdType type); +SilcAsyncOperation +silc_auth_public_key_auth_generate(SilcPublicKey public_key, + SilcPrivateKey private_key, + SilcRng rng, SilcHash hash, + const void *id, SilcIdType type, + SilcAuthGenerated generated, + void *context); /****f* silccore/SilcAuthAPI/silc_auth_public_key_auth_generate_wpub * * SYNOPSIS * - * SilcBuffer + * SilcAsyncOperation * 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); + * SilcIdType type, + * SilcAuthGenerated generated, + * void *context); * * DESCRIPTION * @@ -244,69 +279,108 @@ SilcBuffer silc_auth_public_key_auth_generate(SilcPublicKey public_key, * the public data must be something else than purely random or its * structure mut be set before signing. * + * The `generated' is called to deliver the generated Authentication + * Payload. + * ***/ -SilcBuffer +SilcAsyncOperation 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); + const void *id, SilcIdType type, + SilcAuthGenerated generated, + void *context); + +/****f* silccore/SilcAuthAPI/SilcAuthResult + * + * SYNOPSIS + * + * typedef void (*SilcAuthResult)(SilcBool success, void *context); + * + * DESCRIPTION + * + * Callback of this type is given as argument to silc_auth_verify, + * silc_auth_verify_data, silc_auth_public_key_auth_verify and + * silc_auth_public_key_auth_verify_data to deliver the result of + * the authentication verification. If `success' is FALSE the + * authentication failed. + * + ***/ +typedef void (*SilcAuthResultCb)(SilcBool success, void *context); /****f* silccore/SilcAuthAPI/silc_auth_public_key_auth_verify * * SYNOPSIS * - * SilcBool silc_auth_public_key_auth_verify(SilcAuthPayload payload, - * SilcPublicKey public_key, - * SilcHash hash, - * const void *id, SilcIdType type); + * SilcAsyncOperation + * silc_auth_public_key_auth_verify(SilcAuthPayload payload, + * SilcPublicKey public_key, + * SilcHash hash, + * const void *id, + * SilcIdType type, + * SilcAuthResult result, + * void *context); * * DESCRIPTION * - * Verifies the authentication data. Returns TRUE if authentication was - * successful. + * Verifies the authentication data. Calls the `result' to deliver + * the result of the verification. * ***/ -SilcBool silc_auth_public_key_auth_verify(SilcAuthPayload payload, - SilcPublicKey public_key, - SilcHash hash, - const void *id, - SilcIdType type); +SilcAsyncOperation +silc_auth_public_key_auth_verify(SilcAuthPayload payload, + SilcPublicKey public_key, + SilcHash hash, + const void *id, + SilcIdType type, + SilcAuthResultCb result, + void *context); /****f* silccore/SilcAuthAPI/silc_auth_public_key_auth_verify_data * * SYNOPSIS * - * 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); + * SilcAsyncOperation + * silc_auth_public_key_auth_verify_data(const unsigned char *payload, + * SilcUInt32 payload_len, + * SilcPublicKey public_key, + * SilcHash hash, + * const void *id, + * SilcIdType type, + * SilcAuthResult result, + * void *context); * * DESCRIPTION * * Same as silc_auth_public_key_auth_verify but the payload has not - * been parsed yet. This will parse it. Returns TRUE if authentication - * was successful. + * been parsed yet. This will parse it. Calls the `result' to deliver + * the result of the verification. * ***/ -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); +SilcAsyncOperation +silc_auth_public_key_auth_verify_data(const unsigned char *payload, + SilcUInt32 payload_len, + SilcPublicKey public_key, + SilcHash hash, + const void *id, + SilcIdType type, + SilcAuthResultCb result, + void *context); /****f* silccore/SilcAuthAPI/silc_auth_verify * * SYNOPSIS * - * SilcBool silc_auth_verify(SilcAuthPayload payload, - * SilcAuthMethod auth_method, - * const void *auth_data, SilcUInt32 auth_data_len, - * SilcHash hash, const void *id, SilcIdType type); + * SilcAsyncOperation + * silc_auth_verify(SilcAuthPayload payload, + * SilcAuthMethod auth_method, + * const void *auth_data, + * SilcUInt32 auth_data_len, + * SilcHash hash, + * const void *id, SilcIdType type, + * SilcAuthResult result, void *context); * * DESCRIPTION * @@ -316,22 +390,27 @@ SilcBool silc_auth_public_key_auth_verify_data(const unsigned char *payload, * are the passphrase and its length. The passphrase MUST be UTF-8 * encoded. If the method is public key authentication then the * `auth_data' is the SilcPublicKey and the `auth_data_len' is ignored. + * Calls the `result' to deliver the result of the verification. * ***/ -SilcBool silc_auth_verify(SilcAuthPayload payload, SilcAuthMethod auth_method, - const void *auth_data, SilcUInt32 auth_data_len, - SilcHash hash, const void *id, SilcIdType type); +SilcAsyncOperation +silc_auth_verify(SilcAuthPayload payload, SilcAuthMethod auth_method, + const void *auth_data, SilcUInt32 auth_data_len, + SilcHash hash, const void *id, SilcIdType type, + SilcAuthResultCb result, void *context); /****f* silccore/SilcAuthAPI/silc_auth_verify_data * * SYNOPSIS * - * 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); + * SilcAsyncOperation + * 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, + * SilcAuthResult result, void *context); * * DESCRIPTION * @@ -342,14 +421,17 @@ SilcBool silc_auth_verify(SilcAuthPayload payload, SilcAuthMethod auth_method, * are the passphrase and its length. The passphrase MUST be UTF-8 * encoded. If the method is public key authentication then the * `auth_data' is the SilcPublicKey and the `auth_data_len' is ignored. + * Calls the `result' to deliver the result of the verification. * ***/ -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); +SilcAsyncOperation +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, + SilcAuthResultCb result, void *context); /****s* silccore/SilcAuthAPI/SilcKeyAgreementPayload * diff --git a/lib/silccore/silcmessage.c b/lib/silccore/silcmessage.c index d69ba7fd..9f53d87e 100644 --- a/lib/silccore/silcmessage.c +++ b/lib/silccore/silcmessage.c @@ -36,6 +36,11 @@ /* Payload encoding context */ typedef struct { + SilcBuffer buffer; + SilcBuffer sign; + SilcStack stack; + SilcMessagePayloadEncoded encoded; + void *context; SilcMessageFlags flags; SilcPublicKey public_key; SilcPrivateKey private_key; @@ -43,14 +48,32 @@ typedef struct { SilcCipher cipher; SilcHmac hmac; unsigned char *iv; + unsigned char *pk; + SilcUInt16 pk_len; + SilcUInt16 iv_len; SilcUInt16 payload_len; - SilcID *sid; - SilcID *rid; + SilcID sid; + SilcID rid; } SilcMessageEncode; /************************* Static utility functions *************************/ +static void +silc_message_payload_encode_final(SilcBuffer buffer, + SilcMessageFlags flags, + SilcCipher cipher, + SilcHmac hmac, + unsigned char *iv, + SilcUInt32 iv_len, + SilcUInt32 payload_len, + SilcID *sender_id, + SilcID *receiver_id, + SilcStack stack, + SilcBuffer signature, + SilcMessagePayloadEncoded encoded, + void *context); + /* Returns the data length that fits to the packet. If data length is too big it will be truncated to fit to the payload. */ @@ -140,126 +163,182 @@ silc_message_signed_payload_parse(const unsigned char *data, /* Encodes the data to be signed to SILC_MESSAGE_FLAG_SIGNED Payload */ static SilcBuffer -silc_message_signed_encode_data(const unsigned char *message_payload, +silc_message_signed_encode_data(SilcStack stack, + 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); + sign = silc_buffer_salloc_size(stack, 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); + silc_buffer_sformat(stack, sign, + SILC_STR_DATA(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_sformat(stack, sign, + SILC_STR_UI_XNSTRING(pk, pk_len), + SILC_STR_END); silc_buffer_push(sign, message_payload_len + 4); } return sign; } +/* Signature callback */ + +void silc_message_signed_payload_encode_cb(SilcBool success, + const unsigned char *signature, + SilcUInt32 signature_len, + void *context) +{ + SilcMessageEncode *e = context; + SilcPKCSType pk_type; + SilcStack stack = e->stack; + SilcBuffer buffer, payload; + SilcMessageFlags flags; + SilcCipher cipher; + SilcHmac hmac; + unsigned char *iv; + SilcUInt32 iv_len, payload_len; + SilcID *sid, *rid; + SilcMessagePayloadEncoded encoded; + void *encoded_context; + + if (!success) { + e->encoded(NULL, e->context); + silc_buffer_sfree(stack, e->sign); + silc_sfree(stack, e->pk); + silc_sfree(stack, e); + silc_stack_free(stack); + return; + } + + pk_type = silc_pkcs_get_type(e->private_key); + + /* Encode the SILC_MESSAGE_FLAG_SIGNED Payload */ + buffer = silc_buffer_salloc_size(stack, 4 + e->pk_len + 2 + signature_len); + if (!buffer) { + e->encoded(NULL, e->context); + silc_buffer_sfree(stack, e->sign); + silc_sfree(stack, e->pk); + silc_sfree(stack, e); + silc_stack_free(stack); + return; + } + + silc_buffer_sformat(stack, buffer, + SILC_STR_UI_SHORT(e->pk_len), + SILC_STR_UI_SHORT(pk_type), + SILC_STR_END); + + if (e->pk_len && e->pk) { + silc_buffer_pull(buffer, 4); + silc_buffer_sformat(stack, buffer, + SILC_STR_DATA(e->pk, e->pk_len), + SILC_STR_END); + silc_buffer_push(buffer, 4); + } + + silc_buffer_pull(buffer, 4 + e->pk_len); + silc_buffer_sformat(stack, buffer, + SILC_STR_UI_SHORT(signature_len), + SILC_STR_DATA(signature, signature_len), + SILC_STR_END); + silc_buffer_push(buffer, 4 + e->pk_len); + + SILC_LOG_HEXDUMP(("SIG payload"), buffer->data, silc_buffer_len(buffer)); + + payload = e->buffer; + flags = e->flags; + cipher = e->cipher; + hmac = e->hmac; + iv = e->iv; + iv_len = e->iv_len; + payload_len = e->payload_len; + sid = &e->sid; + rid = &e->rid; + encoded = e->encoded; + encoded_context = e->context; + + silc_sfree(stack, e->pk); + silc_buffer_sfree(stack, e->sign); + silc_sfree(stack, e); + + /* Finalize message payload encoding */ + silc_message_payload_encode_final(payload, flags, cipher, hmac, + iv, iv_len, payload_len, + sid, rid, stack, buffer, + encoded, encoded_context); +} + /* Encodes the SILC_MESSAGE_FLAG_SIGNED Payload and computes the digital signature. */ -static SilcBuffer -silc_message_signed_payload_encode(const unsigned char *message_payload, - SilcUInt32 message_payload_len, - SilcPublicKey public_key, - SilcPrivateKey private_key, - SilcHash hash) +static SilcAsyncOperation +silc_message_signed_payload_encode(SilcBuffer payload, + SilcMessageEncode *e) { - SilcBuffer buffer, sign; - unsigned char auth_data[2048 + 1]; - SilcUInt32 auth_len; + SilcAsyncOperation op; + SilcBuffer sign; unsigned char *pk = NULL; SilcUInt32 pk_len = 0; SilcUInt16 pk_type; - - if (!message_payload || !message_payload_len || !private_key || !hash) + SilcStack stack = e->stack; + SilcHash hash = e->hash; + SilcPublicKey public_key = e->public_key; + SilcPrivateKey private_key = e->private_key; + unsigned char *message_payload; + SilcUInt16 message_payload_len; + + message_payload = payload->head; + message_payload_len = silc_buffer_headlen(payload); + + if (!message_payload || !message_payload_len || !private_key || !hash) { + e->encoded(NULL, e->context); + silc_sfree(stack, e); + silc_stack_free(stack); return NULL; + } if (public_key) { - pk = silc_pkcs_public_key_encode(public_key, &pk_len); - if (!pk) + e->pk = pk = silc_pkcs_public_key_encode(stack, public_key, &pk_len); + if (!pk) { + e->encoded(NULL, e->context); + silc_sfree(stack, e); + silc_stack_free(stack); return NULL; + } + e->pk_len = pk_len; } pk_type = silc_pkcs_get_type(private_key); /* Encode the data to be signed */ - sign = silc_message_signed_encode_data(message_payload, - message_payload_len, - pk, pk_len, pk_type); + e->sign = sign = silc_message_signed_encode_data(stack, message_payload, + message_payload_len, + pk, pk_len, pk_type); if (!sign) { - silc_free(pk); - return NULL; - } - - /* Sign the buffer */ - - /* Compute the hash and the signature. */ - if (!silc_pkcs_sign(private_key, sign->data, silc_buffer_len(sign), - auth_data, sizeof(auth_data) - 1, &auth_len, - TRUE, hash)) { - SILC_LOG_ERROR(("Could not compute signature")); - silc_buffer_clear(sign); - silc_buffer_free(sign); - silc_free(pk); + e->encoded(NULL, e->context); + silc_sfree(stack, pk); + silc_sfree(stack, e); + silc_stack_free(stack); return NULL; } - /* Encode the SILC_MESSAGE_FLAG_SIGNED Payload */ + /* Compute signature */ + op = silc_pkcs_sign(private_key, sign->data, silc_buffer_len(sign), + TRUE, hash, silc_message_signed_payload_encode_cb, e); - buffer = silc_buffer_alloc_size(4 + pk_len + 2 + auth_len); - if (!buffer) { - silc_buffer_clear(sign); - silc_buffer_free(sign); - memset(auth_data, 0, sizeof(auth_data)); - silc_free(pk); - return NULL; - } - - silc_buffer_format(buffer, - SILC_STR_UI_SHORT(pk_len), - SILC_STR_UI_SHORT(pk_type), - SILC_STR_END); - - if (pk_len && pk) { - silc_buffer_pull(buffer, 4); - silc_buffer_format(buffer, - SILC_STR_UI_XNSTRING(pk, pk_len), - SILC_STR_END); - silc_buffer_push(buffer, 4); - } - - silc_buffer_pull(buffer, 4 + pk_len); - silc_buffer_format(buffer, - SILC_STR_UI_SHORT(auth_len), - SILC_STR_UI_XNSTRING(auth_data, auth_len), - SILC_STR_END); - silc_buffer_push(buffer, 4 + pk_len); - - SILC_LOG_HEXDUMP(("sig payload"), buffer->data, silc_buffer_len(buffer)); - - memset(auth_data, 0, sizeof(auth_data)); - silc_buffer_clear(sign); - silc_buffer_free(sign); - silc_free(pk); - - return buffer; + return op; } - /***************************** Payload parsing ******************************/ /* Decrypts the Message Payload. The `data' is the actual Message Payload. */ @@ -300,19 +379,8 @@ SilcBool silc_message_payload_decrypt(unsigned char *data, silc_hmac_update(hmac, receiver_id, receiver_id_len); silc_hmac_final(hmac, mac, &mac_len); if (silc_unlikely(memcmp(data + (data_len - mac_len), mac, mac_len))) { -#if 0 SILC_LOG_DEBUG(("Message MAC does not match")); return FALSE; -#else - /* Check for old style message MAC. Remove this check at some point. */ - silc_hmac_init(hmac); - silc_hmac_update(hmac, data, data_len - mac_len); - silc_hmac_final(hmac, mac, &mac_len); - if (silc_unlikely(memcmp(data + (data_len - mac_len), mac, mac_len))) { - SILC_LOG_DEBUG(("Message MAC does not match")); -#endif - return FALSE; - } } SILC_LOG_DEBUG(("MAC is Ok")); } @@ -477,16 +545,13 @@ SilcBool silc_message_payload_encrypt(unsigned char *data, SilcCipher cipher, SilcHmac hmac) { -#if 0 unsigned char sid[32], rid[32]; SilcUInt32 sid_len = 0, rid_len = 0; -#endif /* 0 */ /* Encrypt payload of the packet */ if (silc_unlikely(!silc_cipher_encrypt(cipher, data, data, data_len, iv))) return FALSE; -#if 0 /* For now this is disabled. Enable at 1.1.x or 1.2 at the latest. */ /* Encode IDs */ silc_id_id2str(&sender_id->u.client_id, SILC_ID_CLIENT, sid, sizeof(sid), &sid_len); @@ -496,15 +561,12 @@ SilcBool silc_message_payload_encrypt(unsigned char *data, else if (receiver_id->type == SILC_ID_CHANNEL) silc_id_id2str(&receiver_id->u.channel_id, SILC_ID_CHANNEL, rid, sizeof(rid), &rid_len); -#endif /* 0 */ /* Compute the MAC of the encrypted message data */ silc_hmac_init(hmac); silc_hmac_update(hmac, data, true_len); -#if 0 silc_hmac_update(hmac, sid, sid_len); silc_hmac_update(hmac, rid, rid_len); -#endif /* 0 */ silc_hmac_final(hmac, data + true_len, NULL); return TRUE; @@ -512,8 +574,7 @@ SilcBool silc_message_payload_encrypt(unsigned char *data, /* Encrypt message payload */ -static int silc_message_payload_encode_encrypt(SilcStack stack, - SilcBuffer buffer, +static int silc_message_payload_encode_encrypt(SilcBuffer buffer, void *value, void *context) { SilcMessageEncode *e = context; @@ -529,82 +590,106 @@ static int silc_message_payload_encode_encrypt(SilcStack stack, if (silc_unlikely(!silc_message_payload_encrypt(buffer->head, e->payload_len, silc_buffer_headlen(buffer), - e->iv, e->sid, e->rid, + e->iv, &e->sid, &e->rid, e->cipher, e->hmac))) return -1; return mac_len; } -/* Compute message signature */ - -static int silc_message_payload_encode_sig(SilcStack stack, - SilcBuffer buffer, - void *value, void *context) +/* Finalize message payload encoding */ + +static void +silc_message_payload_encode_final(SilcBuffer buffer, + SilcMessageFlags flags, + SilcCipher cipher, + SilcHmac hmac, + unsigned char *iv, + SilcUInt32 iv_len, + SilcUInt32 payload_len, + SilcID *sender_id, + SilcID *receiver_id, + SilcStack stack, + SilcBuffer signature, + SilcMessagePayloadEncoded encoded, + void *context) { - SilcMessageEncode *e = context; - SilcBuffer sig; - int len; - - if (!(e->flags & SILC_MESSAGE_FLAG_SIGNED)) - return 0; + SilcMessageEncode e; - sig = silc_message_signed_payload_encode(buffer->head, - silc_buffer_headlen(buffer), - e->public_key, e->private_key, - e->hash); - if (silc_unlikely(!sig)) - return -1; + e.flags = flags; + e.cipher = cipher; + e.hmac = hmac; + e.sid = *sender_id; + e.rid = *receiver_id; + e.iv = iv; + e.payload_len = payload_len; - len = silc_buffer_format(buffer, - SILC_STR_DATA(silc_buffer_data(sig), - silc_buffer_len(sig)), - SILC_STR_END); - if (silc_unlikely(len < 0)) { - silc_buffer_free(sig); - return -1; + /* Encrypt */ + if (silc_buffer_format(buffer, + SILC_STR_DATA(silc_buffer_data(signature), + silc_buffer_len(signature)), + SILC_STR_DATA(iv, iv_len), + SILC_STR_FUNC(silc_message_payload_encode_encrypt, + NULL, &e), + SILC_STR_END) < 0) { + silc_buffer_sfree(stack, buffer); + encoded(NULL, context); + return; } - silc_buffer_free(sig); - return len; + /* Deliver message payload */ + silc_buffer_start(buffer); + encoded(buffer, context); + + silc_buffer_sfree(stack, buffer); + silc_buffer_sfree(stack, signature); + silc_stack_free(stack); } /* Encodes Message Payload into a buffer and returns it. */ -SilcBuffer silc_message_payload_encode(SilcMessageFlags flags, - const unsigned char *data, - SilcUInt32 data_len, - SilcBool generate_iv, - SilcBool private_message, - SilcCipher cipher, - SilcHmac hmac, - SilcRng rng, - SilcPublicKey public_key, - SilcPrivateKey private_key, - SilcHash hash, - SilcID *sender_id, - SilcID *receiver_id, - SilcBuffer buffer) +SilcAsyncOperation +silc_message_payload_encode(SilcMessageFlags flags, + const unsigned char *data, + SilcUInt32 data_len, + SilcBool generate_iv, + SilcBool private_message, + SilcCipher cipher, + SilcHmac hmac, + SilcRng rng, + SilcPublicKey public_key, + SilcPrivateKey private_key, + SilcHash hash, + SilcID *sender_id, + SilcID *receiver_id, + SilcStack stack, + SilcMessagePayloadEncoded encoded, + void *context) { SilcUInt32 pad_len = 0, mac_len = 0, iv_len = 0; unsigned char pad[16], iv[SILC_CIPHER_MAX_IV_SIZE]; - SilcBuffer buf = NULL; - SilcMessageEncode e; + SilcBuffer buffer; int i; SILC_LOG_DEBUG(("Encoding Message Payload")); - if (silc_unlikely(!data_len)) + if (silc_unlikely(!data_len)) { + encoded(NULL, context); return NULL; - if (silc_unlikely(!private_message && (!cipher || !hmac))) + } + if (silc_unlikely(!private_message && (!cipher || !hmac))) { + encoded(NULL, context); return NULL; + } - if (!buffer) { - buf = buffer = silc_buffer_alloc(0); - if (silc_unlikely(!buf)) - return NULL; + stack = silc_stack_alloc(0, stack ? stack : silc_crypto_stack()); + + buffer = silc_buffer_salloc(stack, 0); + if (silc_unlikely(!buffer)) { + encoded(NULL, context); + silc_stack_free(stack); + return NULL; } - silc_buffer_reset(buffer); /* For channel messages IV is always generated */ if (!private_message && !generate_iv) @@ -638,35 +723,55 @@ SilcBuffer silc_message_payload_encode(SilcMessageFlags flags, } } - e.flags = flags; - e.public_key = public_key; - e.private_key = private_key; - e.hash = hash; - e.cipher = cipher; - e.hmac = hmac; - e.sid = sender_id; - e.rid = receiver_id; - e.iv = iv_len ? iv : NULL; - e.payload_len = 6 + data_len + pad_len; - /* Encode the Message Payload */ if (silc_buffer_format(buffer, + SILC_STR_ADVANCE, SILC_STR_UI_SHORT(flags), SILC_STR_UI_SHORT(data_len), SILC_STR_DATA(data, data_len), SILC_STR_UI_SHORT(pad_len), SILC_STR_DATA(pad, pad_len), - SILC_STR_FUNC(silc_message_payload_encode_sig, - NULL, &e), - SILC_STR_DATA(iv, iv_len), - SILC_STR_FUNC(silc_message_payload_encode_encrypt, - NULL, &e), SILC_STR_END) < 0) { - silc_buffer_free(buf); + silc_buffer_sfree(stack, buffer); + encoded(NULL, context); + silc_stack_free(stack); return NULL; } - return buffer; + if (flags & SILC_MESSAGE_FLAG_SIGNED) { + SilcMessageEncode *e = silc_scalloc(stack, 1, sizeof(*e)); + if (!e) { + silc_buffer_sfree(stack, buffer); + encoded(NULL, context); + silc_stack_free(stack); + return NULL; + } + + e->stack = stack; + e->buffer = buffer; + e->flags = flags; + e->public_key = public_key; + e->private_key = private_key; + e->hash = hash; + e->cipher = cipher; + e->hmac = hmac; + e->sid = *sender_id; + e->rid = *receiver_id; + e->iv = iv_len ? iv : NULL; + e->iv_len = iv_len; + e->payload_len = 6 + data_len + pad_len; + + /* Compute signature */ + return silc_message_signed_payload_encode(buffer, e); + } + + /* Finalize */ + silc_message_payload_encode_final(buffer, flags, cipher, hmac, + iv_len ? iv : NULL, iv_len, + 6 + data_len + pad_len, + sender_id, receiver_id, stack, NULL, + encoded, context); + return NULL; } /* Free's Message Payload */ @@ -711,53 +816,59 @@ unsigned char *silc_message_get_mac(SilcMessagePayload payload) /* Verify the signature in SILC_MESSAGE_FLAG_SIGNED Payload */ -SilcAuthResult silc_message_signed_verify(SilcMessagePayload message, - SilcPublicKey remote_public_key, - SilcHash hash) +SilcAsyncOperation +silc_message_signed_verify(SilcMessagePayload message, + SilcPublicKey remote_public_key, + SilcHash hash, + SilcAuthResultCb result, + void *context) { - int ret = SILC_AUTH_FAILED; + SilcAsyncOperation op; SilcBuffer sign, tmp; + SilcStack stack = NULL; SilcMessageSignedPayload sig = &message->sig; if (!(message->flags & SILC_MESSAGE_FLAG_SIGNED) || - !sig->sign_len || !remote_public_key || !hash) - return ret; + !sig->sign_len || !remote_public_key || !hash) { + result(FALSE, context); + return NULL; + } + + if (silc_crypto_stack()) + stack = silc_stack_alloc(0, silc_crypto_stack()); /* Generate the signature verification data, the Message Payload */ - tmp = silc_buffer_alloc_size(6 + message->data_len + message->pad_len); - silc_buffer_format(tmp, - SILC_STR_UI_SHORT(message->flags), - SILC_STR_UI_SHORT(message->data_len), - SILC_STR_UI_XNSTRING(message->data, message->data_len), - SILC_STR_UI_SHORT(message->pad_len), - SILC_STR_UI_XNSTRING(message->pad, message->pad_len), - SILC_STR_END); - sign = silc_message_signed_encode_data(tmp->data, silc_buffer_len(tmp), + tmp = silc_buffer_salloc_size(stack, + 6 + message->data_len + message->pad_len); + silc_buffer_sformat(stack, tmp, + SILC_STR_UI_SHORT(message->flags), + SILC_STR_UI_SHORT(message->data_len), + SILC_STR_DATA(message->data, message->data_len), + SILC_STR_UI_SHORT(message->pad_len), + SILC_STR_DATA(message->pad, message->pad_len), + SILC_STR_END); + sign = silc_message_signed_encode_data(stack, tmp->data, silc_buffer_len(tmp), sig->pk_data, sig->pk_len, sig->pk_type); silc_buffer_clear(tmp); - silc_buffer_free(tmp); - - if (!sign) - return ret; + silc_buffer_sfree(stack, tmp); - /* Verify the authentication data */ - if (!silc_pkcs_verify(remote_public_key, sig->sign_data, sig->sign_len, - silc_buffer_data(sign), silc_buffer_len(sign), hash)) { - silc_buffer_clear(sign); - silc_buffer_free(sign); - SILC_LOG_DEBUG(("Signature verification failed")); - return ret; + if (!sign) { + result(FALSE, context); + silc_stack_free(stack); + return NULL; } - ret = SILC_AUTH_OK; + /* Verify the authentication data */ + op = silc_pkcs_verify(remote_public_key, sig->sign_data, sig->sign_len, + silc_buffer_data(sign), silc_buffer_len(sign), hash, + result, context); silc_buffer_clear(sign); - silc_buffer_free(sign); - - SILC_LOG_DEBUG(("Signature verification successful")); + silc_buffer_sfree(stack, sign); + silc_stack_free(stack); - return ret; + return op; } /* Return the public key from the payload */ diff --git a/lib/silccore/silcmessage.h b/lib/silccore/silcmessage.h index 99e9d988..ef6ed3a8 100644 --- a/lib/silccore/silcmessage.h +++ b/lib/silccore/silcmessage.h @@ -231,34 +231,54 @@ SilcBool silc_message_payload_encrypt(unsigned char *data, SilcCipher cipher, SilcHmac hmac); +/****f* silccore/SilcMessageAPI/SilcMessagePayloadEncoded + * + * SYNOPSIS + * + * typedef void (*SilcMessagePayloadEncoded)(const SilcBuffer message, + * void *context); + * + * DESCRIPTION + * + * This callback is given as arugment to silc_message_payload_encode + * and will be called when the message payload has been encoded. If + * `message' is NULL, encoding failed. + * + ***/ +typedef void (*SilcMessagePayloadEncoded)(SilcBuffer message, + void *context); + /****f* silccore/SilcMessageAPI/silc_message_payload_encode * * SYNOPSIS * - * SilcBuffer silc_message_payload_encode(SilcMessageFlags flags, - * const unsigned char *data, - * SilcUInt32 data_len, - * SilcBool generate_iv, - * SilcBool private_message, - * SilcCipher cipher, - * SilcHmac hmac, - * SilcRng rng, - * SilcPublicKey public_key, - * SilcPrivateKey private_key, - * SilcHash hash, - * SilcID *sender_id, - * SilcID *receiver_id, - * SilcBuffer buffer); + * SilcAsyncOperation + * silc_message_payload_encode(SilcMessageFlags flags, + * const unsigned char *data, + * SilcUInt32 data_len, + * SilcBool generate_iv, + * SilcBool private_message, + * SilcCipher cipher, + * SilcHmac hmac, + * SilcRng rng, + * SilcPublicKey public_key, + * SilcPrivateKey private_key, + * SilcHash hash, + * SilcID *sender_id, + * SilcID *receiver_id, + * SilcStack stack, + * SilcMessagePayloadEncoded encoded, + * void *context); * * DESCRIPTION * - * Encodes a Message Payload into a buffer and returns it. This is - * used to encode channel messages and private messages into a packet. - * If `private_message' is FALSE then this encodes channel message, if - * it is TRUE this encodes private message. If `private_message' is - * TRUE then `generate_iv' MUST be FALSE if the private message key - * `cipher' is not static key (pre-shared key). If it is static key - * then protocol dictates that IV must be present in the Message Payload + * Encodes a Message Payload into a buffer and returns it to the `encoded' + * callback. This is used to encode channel messages and private messages + * into a packet. If `private_message' is FALSE then this encodes channel + * message, if it is TRUE this encodes private message. If + * `private_message' is TRUE then `generate_iv' MUST be FALSE if the private + * message key `cipher' is not static key (pre-shared key). If it is static + * key then protocol dictates that IV must be present in the Message Payload * and `generate_iv' must be TRUE. The caller must know whether the key * is static or not for private messages. If the key was generated with * Key Agreement protocol then `generate_iv' is always FALSE. For @@ -281,26 +301,28 @@ SilcBool silc_message_payload_encrypt(unsigned char *data, * The `sender_id' is the ID message sender and `receiver_id' is ID of * message receiver. * - * If the `buffer' is non-NULL then the payload will be encoded into - * that buffer. The same buffer is returned. Otherwise new buffer is - * allocated and returned. The `buffer' will be automatically enlarged - * if the payload does not fit to it. + * If `stack' is non-NULL the message payload is allocated from stack. + * The memory will be returned back to `stack' after the `encoded' has + * been called. * ***/ -SilcBuffer silc_message_payload_encode(SilcMessageFlags flags, - const unsigned char *data, - SilcUInt32 data_len, - SilcBool generate_iv, - SilcBool private_message, - SilcCipher cipher, - SilcHmac hmac, - SilcRng rng, - SilcPublicKey public_key, - SilcPrivateKey private_key, - SilcHash hash, - SilcID *sender_id, - SilcID *receiver_id, - SilcBuffer buffer); +SilcAsyncOperation +silc_message_payload_encode(SilcMessageFlags flags, + const unsigned char *data, + SilcUInt32 data_len, + SilcBool generate_iv, + SilcBool private_message, + SilcCipher cipher, + SilcHmac hmac, + SilcRng rng, + SilcPublicKey public_key, + SilcPrivateKey private_key, + SilcHash hash, + SilcID *sender_id, + SilcID *receiver_id, + SilcStack stack, + SilcMessagePayloadEncoded encoded, + void *context); /****f* silccore/SilcMessageAPI/silc_message_payload_free * @@ -364,22 +386,27 @@ unsigned char *silc_message_get_mac(SilcMessagePayload payload); * * SYNOPSIS * - * SilcAuthResult + * SilcAsyncOperation * silc_message_signed_verify(SilcMessagePayload message, * SilcPublicKey remote_public_key, - * SilcHash hash); + * SilcHash hash, + * SilcAuthResultCb result, + * void *context); + * * * DESCRIPTION * * This routine can be used to verify the digital signature from the * message indicated by `message'. The signature is present only if - * the SILC_MESSAGE_FLAG_SIGNED is set in the message flags. This - * returns SILC_AUTH_OK if the signature verification was successful. + * the SILC_MESSAGE_FLAG_SIGNED is set in the message flags. The + * result of the verification is returned to `result' callback. * ***/ -SilcAuthResult silc_message_signed_verify(SilcMessagePayload message, - SilcPublicKey remote_public_key, - SilcHash hash); +SilcAsyncOperation silc_message_signed_verify(SilcMessagePayload message, + SilcPublicKey remote_public_key, + SilcHash hash, + SilcAuthResultCb result, + void *context); /****f* silccore/SilcMessageAPI/silc_message_signed_get_public_key * -- 2.24.0