void silc_idlist_del_data(void *entry) { SilcIDListData idata = (SilcIDListData)entry; if (idata->hash) silc_hash_free(idata->hash); idata->hash = NULL; idata->public_key = NULL; }
static void silc_command_reply(SilcClient client, SilcClientConnection conn, SilcCommand command, SilcStatus status, SilcStatus error, va_list ap) { /* If error occurred in client library with our command, print the error */ if (status != SILC_STATUS_OK) fprintf(stderr, "MyBot: COMMAND REPLY %s: %s\n", silc_get_command_name(command), silc_get_status_message(status)); /* Check for successful JOIN. See http://silcnet.org/docs/toolkit/command_reply_args.html for the different arguments the client library returns. */ if (command == SILC_COMMAND_JOIN) { SilcChannelEntry channel; SilcHash sha1hash; (void)va_arg(ap, SilcClientEntry); channel = va_arg(ap, SilcChannelEntry); fprintf(stdout, "MyBot: Joined '%s' channel\n", channel->channel_name); /* Now send the "hello" to the channel */ silc_client_send_channel_message(client, conn, channel, NULL, 0, NULL, "hello", strlen("hello")); fprintf(stdout, "MyBot: Sent 'hello' to channel\n"); /* Now send digitally signed "hello" to the channel. We have to allocate hash function for the signature process. */ silc_hash_alloc("sha1", &sha1hash); silc_client_send_channel_message(client, conn, channel, NULL, SILC_MESSAGE_FLAG_SIGNED, sha1hash, "hello, with signature", strlen("hello, with signature")); silc_hash_free(sha1hash); fprintf(stdout, "MyBot: Sent 'hello, with signature' to channel\n"); } }
int main(int argc, char **argv) { SilcBool success = FALSE; unsigned char digest[32], tmp[4096], digest2[32]; SilcUInt32 tmp_len; SilcHash sha256; if (argc > 1 && !strcmp(argv[1], "-d")) { silc_log_debug(TRUE); silc_log_debug_hexdump(TRUE); silc_log_set_debug_string("*crypt*,*hash*,*sha256*"); } SILC_LOG_DEBUG(("Registering builtin hash functions")); silc_hash_register_default(); SILC_LOG_DEBUG(("Allocating sha256 hash function")); if (!silc_hash_alloc("sha256", &sha256)) { SILC_LOG_DEBUG(("Allocating sha256 hash function failed")); goto err; } SilcUInt64 t1, t2; silc_timer_synchronize(&timer); /* First test vector */ SILC_LOG_DEBUG(("First test vector")); silc_hash_init(sha256); silc_hash_update(sha256, data1, strlen(data1)); memset(digest, 0, sizeof(digest)); t1 = silc_timer_tick(&timer, FALSE); silc_hash_final(sha256, digest); t2 = silc_timer_tick(&timer, TRUE); SILC_LOG_DEBUG(("cycles: %d", t2 - t1)); SILC_LOG_HEXDUMP(("Message"), (unsigned char *)data1, strlen(data1)); SILC_LOG_HEXDUMP(("Digest"), digest, sizeof(digest)); SILC_LOG_HEXDUMP(("Expected digest"), (unsigned char *)data1_digest, sizeof(digest)); if (memcmp(digest, data1_digest, sizeof(digest))) { SILC_LOG_DEBUG(("Hash failed")); goto err; } SILC_LOG_DEBUG(("Hash is successful")); /* Second test vector */ SILC_LOG_DEBUG(("Second test vector")); silc_hash_init(sha256); silc_hash_update(sha256, data2, strlen(data2)); silc_hash_final(sha256, digest); SILC_LOG_HEXDUMP(("Message"), (unsigned char *)data2, strlen(data2)); SILC_LOG_HEXDUMP(("Digest"), digest, sizeof(digest)); SILC_LOG_HEXDUMP(("Expected digest"), (unsigned char *)data2_digest, sizeof(digest)); if (memcmp(digest, data2_digest, sizeof(digest))) { SILC_LOG_DEBUG(("Hash failed")); goto err; } SILC_LOG_DEBUG(("Hash is successful")); /* Third test vector */ SILC_LOG_DEBUG(("Third test vector")); silc_hash_init(sha256); silc_hex2data(data3, tmp, sizeof(tmp), &tmp_len); silc_hash_update(sha256, tmp, tmp_len); silc_hash_final(sha256, digest); SILC_LOG_HEXDUMP(("Message"), tmp, tmp_len); SILC_LOG_HEXDUMP(("Digest"), digest, sizeof(digest)); silc_hex2data(data3_digest, digest2, sizeof(digest2), NULL); SILC_LOG_HEXDUMP(("Expected digest"), (unsigned char *)digest2, sizeof(digest)); if (memcmp(digest, digest2, sizeof(digest))) { SILC_LOG_DEBUG(("Hash failed")); goto err; } SILC_LOG_DEBUG(("Hash is successful")); success = TRUE; err: SILC_LOG_DEBUG(("Testing was %s", success ? "SUCCESS" : "FAILURE")); fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE"); silc_hash_free(sha256); silc_hash_unregister_all(); return success; }
void silc_client_del_connection(SilcClient client, SilcClientConnection conn) { SilcList list; SilcIDCacheEntry entry; SilcFSMThread thread; SILC_LOG_DEBUG(("Freeing connection %p", conn)); silc_schedule_task_del_by_context(conn->internal->schedule, conn); /* Free all cache entries */ if (conn->internal->server_cache) { if (silc_idcache_get_all(conn->internal->server_cache, &list)) { silc_list_start(list); while ((entry = silc_list_get(list))) silc_client_del_server(client, conn, entry->context); } } if (conn->internal->channel_cache) { if (silc_idcache_get_all(conn->internal->channel_cache, &list)) { silc_list_start(list); while ((entry = silc_list_get(list))) { silc_client_empty_channel(client, conn, entry->context); silc_client_del_channel(client, conn, entry->context); } } } if (conn->internal->client_cache) { if (silc_idcache_get_all(conn->internal->client_cache, &list)) { silc_list_start(list); while ((entry = silc_list_get(list))) silc_client_del_client(client, conn, entry->context); } } /* Free ID caches */ if (conn->internal->client_cache) silc_idcache_free(conn->internal->client_cache); if (conn->internal->channel_cache) silc_idcache_free(conn->internal->channel_cache); if (conn->internal->server_cache) silc_idcache_free(conn->internal->server_cache); /* Free thread pool */ silc_list_start(conn->internal->thread_pool); while ((thread = silc_list_get(conn->internal->thread_pool))) silc_fsm_free(thread); silc_free(conn->remote_host); silc_buffer_free(conn->internal->local_idp); silc_buffer_free(conn->internal->remote_idp); silc_mutex_free(conn->internal->lock); if (conn->internal->hash) silc_hash_free(conn->internal->hash); if (conn->internal->sha1hash) silc_hash_free(conn->internal->sha1hash); silc_atomic_uninit16(&conn->internal->cmd_ident); silc_free(conn->internal->away_message); if (conn->internal->rekey) silc_ske_free_rekey_material(conn->internal->rekey); if (conn->internal->cop) silc_async_free(conn->internal->cop); silc_free(conn->internal); memset(conn, 'F', sizeof(*conn)); silc_free(conn); }
int main(int argc, char **argv) { SilcBool success = FALSE; SilcMessagePayload message; SilcBuffer buf; const char *msg = "FOOBAR MESSAGE"; unsigned char *data, tmp[1023], *tmp2; SilcUInt32 data_len; SilcUInt16 flags; int i, n; if (argc > 1 && !strcmp(argv[1], "-d")) { silc_log_debug(TRUE); silc_log_debug_hexdump(TRUE); silc_log_set_debug_string("*message*"); } silc_cipher_register_default(); silc_hash_register_default(); silc_hmac_register_default(); silc_pkcs_register_default(); SILC_LOG_DEBUG(("Load keypair")); if (!silc_load_key_pair("pubkey.pub", "privkey.prv", "", &public_key, &private_key)) { SILC_LOG_DEBUG(("Create keypair")); if (!silc_create_key_pair("rsa", 2048, "pubkey.pub", "privkey.prv", NULL, "", &public_key, &private_key, FALSE)) goto err; } SILC_LOG_DEBUG(("Alloc RNG")); rng = silc_rng_alloc(); silc_rng_init(rng); SILC_LOG_DEBUG(("Alloc AES")); if (!silc_cipher_alloc("aes-128-cbc", &key)) goto err; SILC_LOG_DEBUG(("Alloc SHA-256")); if (!silc_hash_alloc("sha256", &hash)) goto err; SILC_LOG_DEBUG(("Alloc HMAC")); if (!silc_hmac_alloc("hmac-sha256-96", hash, &hmac)) goto err; SILC_LOG_DEBUG(("Set static key: '1234567890123456'")); if (!silc_cipher_set_key(key, "1234567890123456", 16 * 8)) goto err; SILC_LOG_DEBUG(("Set HMAC key: '1234567890123456'")); silc_hmac_set_key(hmac, "1234567890123456", 16); /* Simple private message */ SILC_LOG_DEBUG(("Encoding private message len %d (static key)", strlen(msg))); buf = silc_message_payload_encode(SILC_MESSAGE_FLAG_ACTION | SILC_MESSAGE_FLAG_UTF8 | SILC_MESSAGE_FLAG_ACK, msg, strlen(msg), TRUE, TRUE, key, hmac, rng, NULL, NULL, NULL, NULL); if (!buf) goto err; SILC_LOG_HEXDUMP(("message"), buf->data, silc_buffer_len(buf)); 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, 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; data = silc_message_get_data(message, &data_len); SILC_LOG_HEXDUMP(("Data"), data, data_len); if (data_len != strlen(msg) || memcmp(data, msg, strlen(msg))) goto err; SILC_LOG_HEXDUMP(("MAC"), silc_message_get_mac(message), silc_hmac_len(hmac)); silc_message_payload_free(message); /* Simple private message */ n = 10; SILC_LOG_DEBUG(("Encoding private message len %d (static key)", n)); buf = silc_message_payload_encode(SILC_MESSAGE_FLAG_ACTION | SILC_MESSAGE_FLAG_UTF8 | SILC_MESSAGE_FLAG_ACK, msg, n, TRUE, TRUE, key, hmac, rng, NULL, NULL, NULL, buf); if (!buf) goto err; SILC_LOG_HEXDUMP(("message"), buf->data, silc_buffer_len(buf)); 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, 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; data = silc_message_get_data(message, &data_len); SILC_LOG_HEXDUMP(("Data"), data, data_len); if (data_len != n || memcmp(data, msg, n)) goto err; SILC_LOG_HEXDUMP(("MAC"), silc_message_get_mac(message), silc_hmac_len(hmac)); silc_message_payload_free(message); /* Simple private message */ n = 1; SILC_LOG_DEBUG(("Encoding private message len %d (static key)", n)); buf = silc_message_payload_encode(SILC_MESSAGE_FLAG_ACTION | SILC_MESSAGE_FLAG_UTF8 | SILC_MESSAGE_FLAG_ACK, msg, n, TRUE, TRUE, key, hmac, rng, NULL, NULL, NULL, buf); if (!buf) goto err; SILC_LOG_HEXDUMP(("message"), buf->data, silc_buffer_len(buf)); 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, 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; data = silc_message_get_data(message, &data_len); SILC_LOG_HEXDUMP(("Data"), data, data_len); if (data_len != n || memcmp(data, msg, n)) goto err; SILC_LOG_HEXDUMP(("MAC"), silc_message_get_mac(message), silc_hmac_len(hmac)); silc_message_payload_free(message); /* Simple private message */ for (i = 0; i < sizeof(tmp); i++) tmp[i] = (32 + i) & 127; SILC_LOG_DEBUG(("Encoding private message len %d (static key)", sizeof(tmp))); buf = silc_message_payload_encode(SILC_MESSAGE_FLAG_ACTION | SILC_MESSAGE_FLAG_UTF8 | SILC_MESSAGE_FLAG_ACK, tmp, sizeof(tmp), TRUE, TRUE, key, hmac, rng, NULL, NULL, NULL, buf); if (!buf) goto err; SILC_LOG_HEXDUMP(("message"), buf->data, silc_buffer_len(buf)); 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, 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; data = silc_message_get_data(message, &data_len); SILC_LOG_HEXDUMP(("Data"), data, data_len); if (data_len != sizeof(tmp) || memcmp(data, tmp, sizeof(tmp))) goto err; SILC_LOG_HEXDUMP(("MAC"), silc_message_get_mac(message), silc_hmac_len(hmac)); silc_message_payload_free(message); /* Digitally signed private message */ for (i = 0; i < sizeof(tmp); i++) tmp[i] = (32 + i) & 127; SILC_LOG_DEBUG(("Encoding private message len %d (static key) SIGNED", sizeof(tmp))); buf = silc_message_payload_encode(SILC_MESSAGE_FLAG_ACTION | SILC_MESSAGE_FLAG_UTF8 | SILC_MESSAGE_FLAG_ACK | SILC_MESSAGE_FLAG_SIGNED, tmp, sizeof(tmp), TRUE, TRUE, key, hmac, rng, public_key, private_key, hash, buf); if (!buf) goto err; SILC_LOG_HEXDUMP(("message"), buf->data, silc_buffer_len(buf)); 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, 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_HEXDUMP(("Data"), data, data_len); if (data_len != sizeof(tmp) || memcmp(data, tmp, sizeof(tmp))) 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(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 */ for (i = 0; i < sizeof(tmp) / 2; i++) tmp[i] = (32 + i) & 127; SILC_LOG_DEBUG(("Encoding channel message len %d (static key) SIGNED", sizeof(tmp) / 2)); buf = silc_message_payload_encode(SILC_MESSAGE_FLAG_ACTION | SILC_MESSAGE_FLAG_UTF8 | SILC_MESSAGE_FLAG_ACK | SILC_MESSAGE_FLAG_SIGNED, tmp, sizeof(tmp) / 2, TRUE, FALSE, key, hmac, rng, public_key, private_key, hash, buf); if (!buf) goto err; SILC_LOG_HEXDUMP(("message"), buf->data, silc_buffer_len(buf)); 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_HEXDUMP(("Data"), data, data_len); if (data_len != sizeof(tmp) / 2 || memcmp(data, tmp, sizeof(tmp) / 2)) 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(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 private message (no encryption) */ for (i = 0; i < sizeof(tmp) / 2; i++) tmp[i] = (32 + i) & 127; SILC_LOG_DEBUG(("Encoding private message len %d SIGNED", sizeof(tmp) / 2)); buf = silc_message_payload_encode(SILC_MESSAGE_FLAG_ACTION | SILC_MESSAGE_FLAG_UTF8 | SILC_MESSAGE_FLAG_ACK | SILC_MESSAGE_FLAG_SIGNED, tmp, sizeof(tmp) / 2, FALSE, TRUE, NULL, NULL, rng, public_key, private_key, hash, buf); if (!buf) goto err; SILC_LOG_HEXDUMP(("message"), buf->data, silc_buffer_len(buf)); 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, 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_HEXDUMP(("Data"), data, data_len); if (data_len != sizeof(tmp) / 2 || memcmp(data, tmp, sizeof(tmp) / 2)) goto err; 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(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); silc_free(tmp2); success = TRUE; SILC_LOG_DEBUG(("Cleanup")); silc_pkcs_public_key_free(public_key); silc_pkcs_private_key_free(private_key); silc_cipher_free(key); silc_hash_free(hash); silc_rng_free(rng); err: silc_cipher_unregister_all(); silc_hash_unregister_all(); silc_hmac_unregister_all(); silc_pkcs_unregister_all(); SILC_LOG_DEBUG(("Testing was %s", success ? "SUCCESS" : "FAILURE")); fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE"); return success; }
SilcBool silc_pkcs1_verify(void *public_key, unsigned char *signature, SilcUInt32 signature_len, unsigned char *data, SilcUInt32 data_len, SilcHash hash) { RsaPublicKey *key = public_key; SilcBool ret = FALSE; SilcMPInt mp_tmp2; SilcMPInt mp_dst; unsigned char *verify, unpadded[2048 + 1], hashr[SILC_HASH_MAXLEN]; SilcUInt32 verify_len, len = (key->bits + 7) / 8; SilcBufferStruct di, ldi; SilcHash ihash = NULL; SilcAsn1 asn1 = NULL; char *oid; SILC_LOG_DEBUG(("Verify signature")); asn1 = silc_asn1_alloc(); if (!asn1) return FALSE; silc_mp_init(&mp_tmp2); silc_mp_init(&mp_dst); /* Format the signature into MP int */ silc_mp_bin2mp(signature, signature_len, &mp_tmp2); /* Verify */ silc_rsa_public_operation(key, &mp_tmp2, &mp_dst); /* MP to data */ verify = silc_mp_mp2bin(&mp_dst, len, &verify_len); /* Unpad data */ if (!silc_pkcs1_decode(SILC_PKCS1_BT_PRV1, verify, verify_len, unpadded, sizeof(unpadded), &len)) goto err; silc_buffer_set(&di, unpadded, len); /* If hash isn't given, allocate the one given in digest info */ if (!hash) { /* Decode digest info */ if (!silc_asn1_decode(asn1, &di, SILC_ASN1_OPTS(SILC_ASN1_ACCUMUL), SILC_ASN1_SEQUENCE, SILC_ASN1_SEQUENCE, SILC_ASN1_OID(&oid), SILC_ASN1_END, SILC_ASN1_END, SILC_ASN1_END)) goto err; if (!silc_hash_alloc_by_oid(oid, &ihash)) { SILC_LOG_DEBUG(("Unknown OID %s", oid)); goto err; } hash = ihash; } /* Hash the data */ silc_hash_make(hash, data, data_len, hashr); data = hashr; data_len = silc_hash_len(hash); oid = (char *)silc_hash_get_oid(hash); /* Encode digest info for comparison */ memset(&ldi, 0, sizeof(ldi)); if (!silc_asn1_encode(asn1, &ldi, SILC_ASN1_OPTS(SILC_ASN1_ACCUMUL), SILC_ASN1_SEQUENCE, SILC_ASN1_SEQUENCE, SILC_ASN1_OID(oid), SILC_ASN1_NULL, SILC_ASN1_END, SILC_ASN1_OCTET_STRING(data, data_len), SILC_ASN1_END, SILC_ASN1_END)) goto err; SILC_LOG_HEXDUMP(("DigestInfo remote"), silc_buffer_data(&di), silc_buffer_len(&di)); SILC_LOG_HEXDUMP(("DigestInfo local"), silc_buffer_data(&ldi), silc_buffer_len(&ldi)); /* Compare */ if (silc_buffer_len(&di) == silc_buffer_len(&ldi) && !memcmp(silc_buffer_data(&di), silc_buffer_data(&ldi), silc_buffer_len(&ldi))) ret = TRUE; memset(verify, 0, verify_len); memset(unpadded, 0, sizeof(unpadded)); silc_free(verify); silc_mp_uninit(&mp_tmp2); silc_mp_uninit(&mp_dst); if (hash) memset(hashr, 0, sizeof(hashr)); if (ihash) silc_hash_free(ihash); silc_asn1_free(asn1); return ret; err: memset(verify, 0, verify_len); silc_free(verify); silc_mp_uninit(&mp_tmp2); silc_mp_uninit(&mp_dst); if (ihash) silc_hash_free(ihash); silc_asn1_free(asn1); return FALSE; }