/* Header length plus maximum padding length */
#define SILC_MESSAGE_HLEN 6 + 16
-/* Returns the data length that fits to the packet. If data length is too
- big it will be truncated to fit to the payload. */
-#define SILC_MESSAGE_DATALEN(data_len, header_len) \
- ((data_len + SILC_MESSAGE_HLEN + header_len) > \
- SILC_PACKET_MAX_LEN ? \
- data_len - ((data_len + SILC_MESSAGE_HLEN + header_len) - \
- SILC_PACKET_MAX_LEN) : data_len)
-
-/* Message Payload structure. Contents of this structure is parsed
- from SILC packets. */
-struct SilcMessagePayloadStruct {
- SilcMessageFlags flags;
- SilcUInt16 data_len;
- SilcUInt16 pad_len;
- SilcUInt16 iv_len;
- unsigned char *data;
- unsigned char *pad;
- unsigned char *mac;
- SilcMessageSignedPayload sig;
-};
+/* Maximum message length */
+#define SILC_MESSAGE_MAX_LEN SILC_PACKET_MAX_LEN - SILC_MESSAGE_HLEN - 16
/* Payload encoding context */
typedef struct {
} SilcMessageEncode;
-/****************************** Payload parsing *****************************/
+/************************* Static utility functions *************************/
+
+/* Returns the data length that fits to the packet. If data length is too
+ big it will be truncated to fit to the payload. */
+
+static inline
+SilcUInt32 silc_message_payload_datalen(SilcUInt32 data_len,
+ SilcUInt32 header_len,
+ SilcUInt32 flags,
+ SilcPublicKey public_key,
+ SilcPrivateKey private_key)
+{
+ SilcUInt32 pklen = (flags & SILC_MESSAGE_FLAG_SIGNED && public_key ?
+ silc_pkcs_public_key_get_len(public_key) : 0);
+ SilcUInt32 prlen = (flags & SILC_MESSAGE_FLAG_SIGNED ?
+ silc_pkcs_private_key_get_len(private_key) / 8 : 0);
+ SilcUInt32 dlen = data_len + SILC_MESSAGE_HLEN + header_len + pklen + prlen;
+
+ if (dlen > SILC_MESSAGE_MAX_LEN)
+ data_len -= (dlen - SILC_MESSAGE_MAX_LEN);
+
+ return data_len;
+}
+
+/* Free signed payload */
+
+static void silc_message_signed_payload_free(SilcMessageSignedPayload sig)
+{
+ if (sig->sign_data) {
+ memset(sig->sign_data, 0, sig->sign_len);
+ silc_free(sig->sign_data);
+ }
+ silc_free(sig->pk_data);
+}
+
+/* Parses the SILC_MESSAGE_FLAG_SIGNED Payload */
+
+static SilcBool
+silc_message_signed_payload_parse(const unsigned char *data,
+ SilcUInt32 data_len,
+ SilcMessageSignedPayload sig)
+{
+ SilcBufferStruct buffer;
+ int ret;
+
+ SILC_LOG_DEBUG(("Parsing SILC_MESSAGE_FLAG_SIGNED Payload"));
+
+ SILC_LOG_HEXDUMP(("sig payload"), (unsigned char *)data, data_len);
+
+ silc_buffer_set(&buffer, (unsigned char *)data, data_len);
+
+ /* Parse the payload */
+ ret = silc_buffer_unformat(&buffer,
+ SILC_STR_UI_SHORT(&sig->pk_len),
+ SILC_STR_UI_SHORT(&sig->pk_type),
+ SILC_STR_END);
+ if (ret == -1 || sig->pk_len > data_len - 4) {
+ SILC_LOG_DEBUG(("Malformed public key in SILC_MESSAGE_FLAG_SIGNED "
+ "Payload"));
+ return FALSE;
+ }
+
+ silc_buffer_pull(&buffer, 4);
+ ret = silc_buffer_unformat(&buffer,
+ SILC_STR_UI_XNSTRING_ALLOC(&sig->pk_data,
+ sig->pk_len),
+ SILC_STR_UI16_NSTRING_ALLOC(&sig->sign_data,
+ &sig->sign_len),
+ SILC_STR_END);
+ if (ret == -1 || sig->sign_len > silc_buffer_len(&buffer) -
+ sig->pk_len - 2) {
+ silc_message_signed_payload_free(sig);
+ SILC_LOG_DEBUG(("Malformed SILC_MESSAGE_FLAG_SIGNED Payload"));
+ return FALSE;
+ }
+ silc_buffer_push(&buffer, 4);
+
+ /* Signature must be provided */
+ if (sig->sign_len < 1) {
+ SILC_LOG_DEBUG(("Malformed signature in SILC_MESSAGE_SIGNED_PAYLOAD "
+ "Payload"));
+ silc_message_signed_payload_free(sig);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* Encodes the data to be signed to SILC_MESSAGE_FLAG_SIGNED Payload */
+
+static SilcBuffer
+silc_message_signed_encode_data(const unsigned char *message_payload,
+ SilcUInt32 message_payload_len,
+ unsigned char *pk,
+ SilcUInt32 pk_len, SilcUInt32 pk_type)
+{
+ SilcBuffer sign;
+
+ sign = silc_buffer_alloc_size(message_payload_len + 4 + pk_len);
+ if (!sign)
+ return NULL;
+
+ silc_buffer_format(sign,
+ SILC_STR_UI_XNSTRING(message_payload,
+ message_payload_len),
+ SILC_STR_UI_SHORT(pk_len),
+ SILC_STR_UI_SHORT(pk_type),
+ SILC_STR_END);
+
+ if (pk && pk_len) {
+ silc_buffer_pull(sign, message_payload_len + 4);
+ silc_buffer_format(sign,
+ SILC_STR_UI_XNSTRING(pk, pk_len),
+ SILC_STR_END);
+ silc_buffer_push(sign, message_payload_len + 4);
+ }
+
+ return sign;
+}
+
+/* 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)
+{
+ SilcBuffer buffer, sign;
+ unsigned char auth_data[2048 + 1];
+ SilcUInt32 auth_len;
+ unsigned char *pk = NULL;
+ SilcUInt32 pk_len = 0;
+ SilcUInt16 pk_type;
+
+ if (!message_payload || !message_payload_len || !private_key || !hash)
+ return NULL;
+
+ if (public_key) {
+ pk = silc_pkcs_public_key_encode(public_key, &pk_len);
+ if (!pk)
+ return NULL;
+ }
+ pk_type = silc_pkcs_get_type(public_key);
+
+ /* Encode the data to be signed */
+ sign = silc_message_signed_encode_data(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, hash)) {
+ SILC_LOG_ERROR(("Could not compute signature"));
+ silc_buffer_clear(sign);
+ silc_buffer_free(sign);
+ silc_free(pk);
+ return NULL;
+ }
+
+ /* Encode the SILC_MESSAGE_FLAG_SIGNED Payload */
+
+ buffer = silc_buffer_alloc_size(4 + pk_len + 2 + auth_len);
+ if (!buffer) {
+ silc_buffer_clear(sign);
+ silc_buffer_free(sign);
+ 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;
+}
+
+
+/***************************** Payload parsing ******************************/
/* Decrypts the Message Payload. The `data' is the actual Message Payload. */
SilcBool private_message,
SilcBool static_key,
SilcCipher cipher,
- SilcHmac hmac)
+ SilcHmac hmac,
+ SilcStack stack,
+ SilcBool no_allocation,
+ SilcMessagePayload message)
{
SilcBufferStruct buffer;
- SilcMessagePayload newp;
+ SilcMessagePayload newp = NULL;
int ret;
SilcUInt32 mac_len = 0, iv_len = 0;
if (cipher && (!private_message || (private_message && static_key)))
iv_len = silc_cipher_get_block_len(cipher);
- newp = silc_calloc(1, sizeof(*newp));
- if (!newp)
- return NULL;
+ if (!message) {
+ newp = message = silc_calloc(1, sizeof(*newp));
+ if (!newp)
+ return NULL;
+ }
+ memset(message, 0, sizeof(*message));
+ message->allocated = (stack || no_allocation ? FALSE : TRUE);
/* Parse the Message Payload. */
- ret = silc_buffer_unformat(&buffer,
- SILC_STR_UI_SHORT(&newp->flags),
- SILC_STR_UI16_NSTRING_ALLOC(&newp->data,
- &newp->data_len),
- SILC_STR_UI16_NSTRING_ALLOC(&newp->pad,
- &newp->pad_len),
- SILC_STR_END);
+ if (!no_allocation)
+ ret = silc_buffer_sunformat(stack, &buffer,
+ SILC_STR_UI_SHORT(&message->flags),
+ SILC_STR_UI16_NSTRING_ALLOC(&message->data,
+ &message->data_len),
+ SILC_STR_UI16_NSTRING_ALLOC(&message->pad,
+ &message->pad_len),
+ SILC_STR_END);
+ else
+ ret = silc_buffer_unformat(&buffer,
+ SILC_STR_UI_SHORT(&message->flags),
+ SILC_STR_UI16_NSTRING(&message->data,
+ &message->data_len),
+ SILC_STR_UI16_NSTRING(&message->pad,
+ &message->pad_len),
+ SILC_STR_END);
if (ret == -1)
goto err;
- if ((newp->data_len > silc_buffer_len(&buffer) - 6 - mac_len - iv_len) ||
- (newp->pad_len + newp->data_len > silc_buffer_len(&buffer) -
+ if ((message->data_len > silc_buffer_len(&buffer) - 6 - mac_len - iv_len) ||
+ (message->pad_len + message->data_len > silc_buffer_len(&buffer) -
6 - mac_len - iv_len)) {
SILC_LOG_ERROR(("Incorrect Message Payload in packet"));
goto err;
}
/* Parse Signed Message Payload if provided */
- if (newp->flags & SILC_MESSAGE_FLAG_SIGNED &&
- newp->data_len + newp->pad_len + 6 + mac_len +
+ if (message->flags & SILC_MESSAGE_FLAG_SIGNED &&
+ message->data_len + message->pad_len + 6 + mac_len +
iv_len < silc_buffer_len(&buffer)) {
- newp->sig =
- silc_message_signed_payload_parse(buffer.data + 6 + newp->data_len +
- newp->pad_len,
- silc_buffer_len(&buffer) -
- iv_len - mac_len - 6 - newp->data_len -
- newp->pad_len);
+ if (!silc_message_signed_payload_parse(buffer.data + 6 +
+ message->data_len +
+ message->pad_len,
+ silc_buffer_len(&buffer) -
+ iv_len - mac_len - 6 -
+ message->data_len -
+ message->pad_len,
+ &message->sig))
+ goto err;
}
/* Parse MAC from the payload */
if (mac_len)
- newp->mac = buffer.data + (silc_buffer_len(&buffer) - mac_len);
+ message->mac = buffer.data + (silc_buffer_len(&buffer) - mac_len);
return newp;
err:
- silc_message_payload_free(newp);
+ if (newp)
+ silc_message_payload_free(newp);
return NULL;
}
if (hmac)
mac_len = silc_hmac_len(hmac);
- data_len = SILC_MESSAGE_DATALEN(data_len, mac_len + iv_len);
+ data_len = silc_message_payload_datalen(data_len, mac_len + iv_len, flags,
+ public_key, private_key);
/* Calculate length of padding. IV is not included into the calculation
since it is not encrypted. */
{
if (payload->data) {
memset(payload->data, 0, payload->data_len);
- silc_free(payload->data);
+ if (payload->allocated)
+ silc_free(payload->data);
+ }
+ if (payload->allocated) {
+ silc_free(payload->pad);
+ silc_free(payload);
}
- if (payload->sig)
- silc_message_signed_payload_free(payload->sig);
- silc_free(payload->pad);
- silc_free(payload);
+ silc_message_signed_payload_free(&payload->sig);
}
/* Return flags */
return payload->mac;
}
-/* Return signature of the message */
-
-SilcMessageSignedPayload
-silc_message_get_signature(SilcMessagePayload payload)
-{
- return payload->sig;
-}
-
-
-/************************ Message Signature Payload *************************/
-
-/* The SILC_MESSAGE_FLAG_SIGNED Payload */
-struct SilcMessageSignedPayloadStruct {
- SilcUInt16 pk_len;
- SilcUInt16 pk_type;
- SilcUInt16 sign_len;
- unsigned char *pk_data;
- unsigned char *sign_data;
-};
-
-/* Encodes the data to be signed to SILC_MESSAGE_FLAG_SIGNED Payload */
-
-static SilcBuffer
-silc_message_signed_encode_data(const unsigned char *message_payload,
- SilcUInt32 message_payload_len,
- unsigned char *pk,
- SilcUInt32 pk_len, SilcUInt32 pk_type)
-{
- SilcBuffer sign;
-
- sign = silc_buffer_alloc_size(message_payload_len + 4 + pk_len);
- if (!sign)
- return NULL;
-
- silc_buffer_format(sign,
- SILC_STR_UI_XNSTRING(message_payload,
- message_payload_len),
- SILC_STR_UI_SHORT(pk_len),
- SILC_STR_UI_SHORT(pk_type),
- SILC_STR_END);
-
- if (pk && pk_len) {
- silc_buffer_pull(sign, message_payload_len + 4);
- silc_buffer_format(sign,
- SILC_STR_UI_XNSTRING(pk, pk_len),
- SILC_STR_END);
- silc_buffer_push(sign, message_payload_len + 4);
- }
-
- return sign;
-}
-
-/* Parses the SILC_MESSAGE_FLAG_SIGNED Payload */
-
-SilcMessageSignedPayload
-silc_message_signed_payload_parse(const unsigned char *data,
- SilcUInt32 data_len)
-{
- SilcMessageSignedPayload sig;
- SilcBufferStruct buffer;
- int ret;
-
- SILC_LOG_DEBUG(("Parsing SILC_MESSAGE_FLAG_SIGNED Payload"));
-
- SILC_LOG_HEXDUMP(("sig payload"), (unsigned char *)data, data_len);
-
- silc_buffer_set(&buffer, (unsigned char *)data, data_len);
- sig = silc_calloc(1, sizeof(*sig));
- if (!sig)
- return NULL;
-
- /* Parse the payload */
- ret = silc_buffer_unformat(&buffer,
- SILC_STR_UI_SHORT(&sig->pk_len),
- SILC_STR_UI_SHORT(&sig->pk_type),
- SILC_STR_END);
- if (ret == -1 || sig->pk_len > data_len - 4) {
- silc_message_signed_payload_free(sig);
- SILC_LOG_DEBUG(("Malformed public key in SILC_MESSAGE_FLAG_SIGNED "
- "Payload"));
- return NULL;
- }
-
- silc_buffer_pull(&buffer, 4);
- ret = silc_buffer_unformat(&buffer,
- SILC_STR_UI_XNSTRING_ALLOC(&sig->pk_data,
- sig->pk_len),
- SILC_STR_UI16_NSTRING_ALLOC(&sig->sign_data,
- &sig->sign_len),
- SILC_STR_END);
- if (ret == -1 || sig->sign_len > silc_buffer_len(&buffer) -
- sig->pk_len - 2) {
- silc_message_signed_payload_free(sig);
- SILC_LOG_DEBUG(("Malformed SILC_MESSAGE_FLAG_SIGNED Payload"));
- return NULL;
- }
- silc_buffer_push(&buffer, 4);
-
- /* Signature must be provided */
- if (sig->sign_len < 1) {
- SILC_LOG_DEBUG(("Malformed signature in SILC_MESSAGE_SIGNED_PAYLOAD "
- "Payload"));
- silc_message_signed_payload_free(sig);
- return NULL;
- }
-
- return sig;
-}
-
-/* Encodes the SILC_MESSAGE_FLAG_SIGNED Payload and computes the digital
- signature. */
-
-SilcBuffer
-silc_message_signed_payload_encode(const unsigned char *message_payload,
- SilcUInt32 message_payload_len,
- SilcPublicKey public_key,
- SilcPrivateKey private_key,
- SilcHash hash)
-{
- SilcBuffer buffer, sign;
- unsigned char auth_data[2048 + 1];
- SilcUInt32 auth_len;
- unsigned char *pk = NULL;
- SilcUInt32 pk_len = 0;
- SilcUInt16 pk_type;
-
- if (!message_payload || !message_payload_len || !private_key || !hash)
- return NULL;
-
- if (public_key) {
- pk = silc_pkcs_public_key_encode(public_key, &pk_len);
- if (!pk)
- return NULL;
- }
- pk_type = silc_pkcs_get_type(public_key);
-
- /* Encode the data to be signed */
- sign = silc_message_signed_encode_data(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, hash)) {
- SILC_LOG_ERROR(("Could not compute signature"));
- silc_buffer_clear(sign);
- silc_buffer_free(sign);
- silc_free(pk);
- return NULL;
- }
-
- /* Encode the SILC_MESSAGE_FLAG_SIGNED Payload */
-
- buffer = silc_buffer_alloc_size(4 + pk_len + 2 + auth_len);
- if (!buffer) {
- silc_buffer_clear(sign);
- silc_buffer_free(sign);
- 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;
-}
-
-/* Free the payload */
-
-void silc_message_signed_payload_free(SilcMessageSignedPayload sig)
-{
- memset(sig->sign_data, 0, sig->sign_len);
- silc_free(sig->sign_data);
- silc_free(sig->pk_data);
- silc_free(sig);
-}
-
/* Verify the signature in SILC_MESSAGE_FLAG_SIGNED Payload */
-int silc_message_signed_verify(SilcMessageSignedPayload sig,
- SilcMessagePayload message,
+int silc_message_signed_verify(SilcMessagePayload message,
SilcPublicKey remote_public_key,
SilcHash hash)
{
int ret = SILC_AUTH_FAILED;
SilcBuffer sign, tmp;
+ SilcMessageSignedPayload sig = &message->sig;
- if (!sig || !remote_public_key || !hash)
+ if (!(message->flags & SILC_MESSAGE_FLAG_SIGNED) ||
+ !sig->sign_len || !remote_public_key || !hash)
return ret;
/* Generate the signature verification data, the Message Payload */
return ret;
/* Verify the authentication data */
- if (!silc_pkcs_verify(remote_public_key, sig->sign_data,
- sig->sign_len,
- sign->data, silc_buffer_len(sign), hash)) {
-
+ 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 the public key from the payload */
SilcPublicKey
-silc_message_signed_get_public_key(SilcMessageSignedPayload sig,
+silc_message_signed_get_public_key(SilcMessagePayload payload,
const unsigned char **pk_data,
SilcUInt32 *pk_data_len)
{
SilcPublicKey pk;
+ SilcMessageSignedPayload sig = &payload->sig;
if (!sig->pk_data)
return NULL;
* DESCRIPTION
*
* This interface includes the implementation of the Message Payload that
- * is used to send private messages and channel messages.
- *
- * This interface defines also the SILC_MESSAGE_FLAG_SIGNED Payload,
- * which defines how channel messages and private messages can be digitally
- * signed. This interface provides the payload parsing, encoding,
- * signature computing and signature verification routines.
+ * is used to send private messages and channel messages. The interface
+ * is also able to automatically provide digital signature in the messages
+ * if it is requested. Message digital signatures may also be verified with
+ * this interface.
*
***/
*
* NAME
*
- * typedef struct SilcMessagePayloadStruct *SilcMessagePayload;
+ * typedef struct SilcMessagePayloadObject
+ * *SilcMessagePayload, SilcMessagePayloadStruct;
*
*
* DESCRIPTION
* silc_message_payload_free function.
*
***/
-typedef struct SilcMessagePayloadStruct *SilcMessagePayload;
-
-/****s* silccore/SilcMessageAPI/SilcMessageSignedPayload
- *
- * NAME
- *
- * typedef struct SilcMessageSignedPayloadStruct *SilcMessageSignedPayload;
- *
- *
- * DESCRIPTION
- *
- * This context represents the SILC_MESSAGE_FLAG_SIGNED Payload which
- * is used with channel messages and private messages to indicate that
- * the message is digitally signed. This payload may include the
- * message sender's public key and it includes the digital signature.
- * This payload MUST NOT be used in any other context except with
- * channel and private message sending and reception.
- *
- ***/
-typedef struct SilcMessageSignedPayloadStruct *SilcMessageSignedPayload;
+typedef struct SilcMessagePayloadObject
+ *SilcMessagePayload, SilcMessagePayloadStruct;
/****d* silccore/SilcMessageAPI/SilcMessageFlags
*
* SilcBool private_message,
* SilcBool static_key,
* SilcCipher cipher,
- * SilcHmac hmac);
+ * SilcHmac hmac,
+ * SilcStack stack,
+ * SilcBool no_allocation,
+ * SilcMessagePayload message);
*
* DESCRIPTION
*
* then this assumes that the packet was decrypted with session keys
* (no private message key) and this merely decodes the payload.
*
+ * If the `message' is non-NULL then that pre-allocated context is
+ * used in parsing. Same context is returned. Otherwise new context
+ * is allocated and returned. If the `stack' is non-NULL then memory
+ * is allocated from that stack. If `no_allocation' is TRUE then the
+ * `message' must be provided and data is merely parsed and referenced
+ * from `payload' and will become invalid when `payload' invalidates.
+ * If `no_allocation' is TRUE the routine does not do any allocations.
+ *
***/
SilcMessagePayload
silc_message_payload_parse(unsigned char *payload,
SilcBool private_message,
SilcBool static_key,
SilcCipher cipher,
- SilcHmac hmac);
+ SilcHmac hmac,
+ SilcStack stack,
+ SilcBool no_allocation,
+ SilcMessagePayload message);
/****f* silccore/SilcMessageAPI/silc_message_payload_encrypt
*
***/
unsigned char *silc_message_get_mac(SilcMessagePayload payload);
-/****f* silccore/SilcMessageAPI/silc_message_get_signature
- *
- * SYNOPSIS
- *
- * SilcMessageSignedPayload
- * silc_message_get_signature(SilcMessagePayload payload);
- *
- * DESCRIPTION
- *
- * Returns the pointer to the signature of the message if the
- * SILC_MESSAGE_FLAG_SIGNED was set. If the flag is set and this
- * function returns NULL then error had occurred and the signature
- * could not be retrieved from the message.
- *
- * The caller SHOULD verify the signature by calling the
- * silc_message_signed_verify function. Caller must not free the
- * returned payload pointer.
- *
- ***/
-SilcMessageSignedPayload
-silc_message_get_signature(SilcMessagePayload payload);
-
-/****f* silccore/SilcMessageAPI/silc_message_signed_payload_parse
- *
- * SYNOPSIS
- *
- * SilcMessageSignedPayload
- * silc_message_signed_payload_parse(const unsigned char *data,
- * SilcUInt32 data_len);
- *
- * DESCRIPTION
- *
- * Parses the SilcMessageSignedPayload Payload from the `data' of
- * length of `data_len' bytes. The `data' must be payload without
- * the actual message payload. Returns the parsed payload or NULL
- * on error. Caller must free the returned payload. Application
- * usually does not need to call this since the function
- * silc_message_payload_parse calls this automatically for signed
- * messages.
- *
- ***/
-SilcMessageSignedPayload
-silc_message_signed_payload_parse(const unsigned char *data,
- SilcUInt32 data_len);
-
-/****f* silccore/SilcMessageAPI/silc_message_signed_payload_encode
- *
- * SYNOPSIS
- *
- * SilcBuffer
- * silc_message_signed_payload_encode(const unsigned char *message_payload,
- * SilcUInt32 message_payload_len,
- * SilcPublicKey public_key,
- * SilcPrivateKey private_key,
- * SilcHash hash);
- *
- * DESCRIPTION
- *
- * Encodes the SilcMessageSignedPayload Payload and computes the
- * digital signature. The `message_payload' is the message data that
- * is used in the signature computation. The encoding of the buffer
- * is specified in the SILC protocol. If `public_key' is provided
- * then the public key included in the payload. The `private_key'
- * is used to produce the signature. This function returns the encoded
- * payload with the signature or NULL on error. Caller must free the
- * returned buffer. The `hash' SHOULD be SHA-1 hash function.
- *
- * Application usually does not need to call this since the function
- * silc_message_payload_encode calls this automatically if the caller
- * wants to sign the message.
- *
- ***/
-SilcBuffer
-silc_message_signed_payload_encode(const unsigned char *message_payload,
- SilcUInt32 message_payload_len,
- SilcPublicKey public_key,
- SilcPrivateKey private_key,
- SilcHash hash);
-
-/****f* silccore/SilcMessageAPI/silc_message_signed_payload_free
- *
- * SYNOPSIS
- *
- * void silc_message_signed_payload_free(SilcMessageSignedPayload sig);
- *
- * DESCRIPTION
- *
- * Frees the SilcMessageSignedPayload Payload.
- *
- ***/
-void silc_message_signed_payload_free(SilcMessageSignedPayload sig);
-
/****f* silccore/SilcMessageAPI/silc_message_signed_verify
*
* SYNOPSIS
*
- * int silc_message_signed_verify(SilcMessageSignedPayload sig,
- * SilcMessagePayload message,
+ * int silc_message_signed_verify(SilcMessagePayload message,
* SilcPublicKey remote_public_key,
* SilcHash hash);
*
* DESCRIPTION
*
- * This routine can be used to verify the signature found in
- * SilcMessageSignedPayload Payload. This returns SILC_AUTH_OK if the
- * signature verification was successful.
+ * 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.
*
***/
-int silc_message_signed_verify(SilcMessageSignedPayload sig,
- SilcMessagePayload message,
+int silc_message_signed_verify(SilcMessagePayload message,
SilcPublicKey remote_public_key,
SilcHash hash);
* SYNOPSIS
*
* SilcPublicKey
- * silc_message_signed_get_public_key(SilcMessageSignedPayload sig,
+ * silc_message_signed_get_public_key(SilcMessagePayload payload,
* const unsigned char **pk_data,
* SilcUInt32 *pk_data_len);
*
* DESCRIPTION
*
- * Returns the decoded SilcPublicKey from the SilcMessageSignedPayload
- * Payload or NULL if it does not include public key. The caller must
- * free the returned public key pointer. This also returns the raw
- * public key (before decoding) into `pk_data' and `pk_data_len' if
- * they are provided. The caller must not free these pointers.
+ * Returns the decoded SilcPublicKey from the message payload or NULL
+ * if it does not include public key. The caller must free the returned
+ * public key pointer. This also returns the raw public key (before
+ * decoding) into `pk_data' and `pk_data_len' if they are provided. The
+ * caller must not free these pointers.
*
***/
SilcPublicKey
-silc_message_signed_get_public_key(SilcMessageSignedPayload sig,
+silc_message_signed_get_public_key(SilcMessagePayload payload,
const unsigned char **pk_data,
SilcUInt32 *pk_data_len);
+#include "silcmessage_i.h"
+
#endif /* SILCMESSAGE_H */
SilcMessagePayload message;
SilcBuffer buf;
const char *msg = "FOOBAR MESSAGE";
- unsigned char *data, tmp[1023];
+ unsigned char *data, tmp[1023], *tmp2;
SilcUInt32 data_len;
SilcUInt16 flags;
int i, n;
- SilcMessageSignedPayload sig;
if (argc > 1 && !strcmp(argv[1], "-d")) {
silc_log_debug(TRUE);
SILC_LOG_DEBUG(("Parsing private messsage (static key)"));
message = silc_message_payload_parse(silc_buffer_data(buf),
silc_buffer_len(buf), TRUE, TRUE,
- key, hmac);
+ key, hmac, NULL, FALSE, NULL);
if (!message)
goto err;
flags = silc_message_get_flags(message);
SILC_LOG_DEBUG(("Parsing private messsage (static key)"));
message = silc_message_payload_parse(silc_buffer_data(buf),
silc_buffer_len(buf), TRUE, TRUE,
- key, hmac);
+ key, hmac, NULL, FALSE, NULL);
if (!message)
goto err;
flags = silc_message_get_flags(message);
SILC_LOG_DEBUG(("Parsing private messsage (static key)"));
message = silc_message_payload_parse(silc_buffer_data(buf),
silc_buffer_len(buf), TRUE, TRUE,
- key, hmac);
+ key, hmac, NULL, FALSE, NULL);
if (!message)
goto err;
flags = silc_message_get_flags(message);
SILC_LOG_DEBUG(("Parsing private messsage (static key)"));
message = silc_message_payload_parse(silc_buffer_data(buf),
silc_buffer_len(buf), TRUE, TRUE,
- key, hmac);
+ key, hmac, NULL, FALSE, NULL);
if (!message)
goto err;
flags = silc_message_get_flags(message);
SILC_LOG_DEBUG(("Parsing private messsage (static key)"));
message = silc_message_payload_parse(silc_buffer_data(buf),
silc_buffer_len(buf), TRUE, TRUE,
- key, hmac);
+ key, hmac, NULL, FALSE, NULL);
if (!message)
goto err;
flags = silc_message_get_flags(message);
goto err;
SILC_LOG_HEXDUMP(("MAC"), silc_message_get_mac(message),
silc_hmac_len(hmac));
- SILC_LOG_DEBUG(("Get signature"));
- sig = silc_message_get_signature(message);
- if (!sig)
- goto err;
SILC_LOG_DEBUG(("Verifying signature"));
- if (silc_message_signed_verify(sig, message, public_key, hash) !=
+ if (silc_message_signed_verify(message, public_key, hash) !=
SILC_AUTH_OK)
goto err;
SILC_LOG_DEBUG(("Signature Ok"));
SILC_LOG_DEBUG(("Get public key"));
- pk2 = silc_message_signed_get_public_key(sig, NULL, NULL);
+ pk2 = silc_message_signed_get_public_key(message, NULL, NULL);
if (!pk2)
goto err;
SILC_LOG_DEBUG(("Verify public key"));
SILC_LOG_DEBUG(("Parsing channel messsage (static key)"));
message = silc_message_payload_parse(silc_buffer_data(buf),
silc_buffer_len(buf), FALSE, TRUE,
- key, hmac);
+ key, hmac, NULL, FALSE, NULL);
if (!message)
goto err;
flags = silc_message_get_flags(message);
goto err;
SILC_LOG_HEXDUMP(("MAC"), silc_message_get_mac(message),
silc_hmac_len(hmac));
- SILC_LOG_DEBUG(("Get signature"));
- sig = silc_message_get_signature(message);
- if (!sig)
- goto err;
SILC_LOG_DEBUG(("Verifying signature"));
- if (silc_message_signed_verify(sig, message, public_key, hash) !=
+ if (silc_message_signed_verify(message, public_key, hash) !=
SILC_AUTH_OK)
goto err;
SILC_LOG_DEBUG(("Signature Ok"));
SILC_LOG_DEBUG(("Get public key"));
- pk2 = silc_message_signed_get_public_key(sig, NULL, NULL);
+ pk2 = silc_message_signed_get_public_key(message, NULL, NULL);
if (!pk2)
goto err;
SILC_LOG_DEBUG(("Verify public key"));
SILC_LOG_DEBUG(("Parsing private messsage (static key)"));
message = silc_message_payload_parse(silc_buffer_data(buf),
silc_buffer_len(buf), TRUE, FALSE,
- NULL, NULL);
+ NULL, NULL, NULL, FALSE, NULL);
if (!message)
goto err;
flags = silc_message_get_flags(message);
SILC_LOG_HEXDUMP(("Data"), data, data_len);
if (data_len != sizeof(tmp) / 2 || memcmp(data, tmp, sizeof(tmp) / 2))
goto err;
- SILC_LOG_DEBUG(("Get signature"));
- sig = silc_message_get_signature(message);
- if (!sig)
+ SILC_LOG_DEBUG(("Verifying signature"));
+ if (silc_message_signed_verify(message, public_key, hash) !=
+ SILC_AUTH_OK)
+ goto err;
+ SILC_LOG_DEBUG(("Signature Ok"));
+ SILC_LOG_DEBUG(("Get public key"));
+ pk2 = silc_message_signed_get_public_key(message, NULL, NULL);
+ if (!pk2)
+ goto err;
+ SILC_LOG_DEBUG(("Verify public key"));
+ if (!silc_pkcs_public_key_compare(public_key, pk2))
+ goto err;
+ SILC_LOG_DEBUG(("Public key Ok"));
+ silc_pkcs_public_key_free(pk2);
+ silc_message_payload_free(message);
+
+ /* Digitally signed channel message (LARGE) */
+ n = 65550;
+ tmp2 = silc_malloc(n);
+ if (!tmp2)
+ goto err;
+ SILC_LOG_DEBUG(("Encoding channel message len %d (static key) SIGNED LARGE",
+ n));
+ buf = silc_message_payload_encode(SILC_MESSAGE_FLAG_ACTION |
+ SILC_MESSAGE_FLAG_UTF8 |
+ SILC_MESSAGE_FLAG_ACK |
+ SILC_MESSAGE_FLAG_SIGNED,
+ tmp2, n, TRUE, FALSE,
+ key, hmac, rng,
+ public_key, private_key, hash, buf);
+ if (!buf)
+ goto err;
+ SILC_LOG_DEBUG(("Message length: %d", silc_buffer_len(buf)));
+ if (silc_buffer_len(buf) > SILC_PACKET_MAX_LEN)
+ goto err;
+ SILC_LOG_DEBUG(("Parsing channel messsage (static key)"));
+ message = silc_message_payload_parse(silc_buffer_data(buf),
+ silc_buffer_len(buf), FALSE, TRUE,
+ key, hmac, NULL, FALSE, NULL);
+ if (!message)
+ goto err;
+ flags = silc_message_get_flags(message);
+ SILC_LOG_DEBUG(("Flags: %x", flags));
+ if (!(flags & SILC_MESSAGE_FLAG_ACTION))
+ goto err;
+ if (!(flags & SILC_MESSAGE_FLAG_UTF8))
+ goto err;
+ if (!(flags & SILC_MESSAGE_FLAG_ACK))
goto err;
+ if (!(flags & SILC_MESSAGE_FLAG_SIGNED))
+ goto err;
+ data = silc_message_get_data(message, &data_len);
+ SILC_LOG_DEBUG(("Data len: %d", data_len));
+ if (silc_buffer_len(buf) > SILC_PACKET_MAX_LEN)
+ goto err;
+ SILC_LOG_HEXDUMP(("MAC"), silc_message_get_mac(message),
+ silc_hmac_len(hmac));
SILC_LOG_DEBUG(("Verifying signature"));
- if (silc_message_signed_verify(sig, message, public_key, hash) !=
+ if (silc_message_signed_verify(message, public_key, hash) !=
SILC_AUTH_OK)
goto err;
SILC_LOG_DEBUG(("Signature Ok"));
SILC_LOG_DEBUG(("Get public key"));
- pk2 = silc_message_signed_get_public_key(sig, NULL, NULL);
+ pk2 = silc_message_signed_get_public_key(message, NULL, NULL);
if (!pk2)
goto err;
SILC_LOG_DEBUG(("Verify public key"));
SILC_LOG_DEBUG(("Public key Ok"));
silc_pkcs_public_key_free(pk2);
silc_message_payload_free(message);
+ silc_free(tmp2);
success = TRUE;