/* 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;
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;
}
/* 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,
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;
}
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);
}
}
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)
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;
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
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'
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:
}
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;
}
/******************************************************************************
*
* 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,
* 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,
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
* 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
*
* 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
*
* 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
*
* 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
*
/* Payload encoding context */
typedef struct {
+ SilcBuffer buffer;
+ SilcBuffer sign;
+ SilcStack stack;
+ SilcMessagePayloadEncoded encoded;
+ void *context;
SilcMessageFlags flags;
SilcPublicKey public_key;
SilcPrivateKey private_key;
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. */
/* 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. */
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"));
}
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);
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;
/* 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;
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)
}
}
- 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 */
/* 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 */
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
* 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
*
*
* 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
*