+ SilcChannelPrivateKey entry;
+ unsigned char hash[SILC_HASH_MAXLEN];
+ SilcSKEKeyMaterial *keymat;
+
+ assert(client && channel);
+
+ if (!cipher)
+ cipher = SILC_DEFAULT_CIPHER;
+ if (!hmac)
+ hmac = SILC_DEFAULT_HMAC;
+
+ if (!silc_cipher_is_supported(cipher))
+ return FALSE;
+
+ if (!silc_hmac_is_supported(hmac))
+ return FALSE;
+
+ /* Produce the key material */
+ keymat = silc_calloc(1, sizeof(*keymat));
+ if (silc_ske_process_key_material_data(key, key_len, 16, 256, 16,
+ client->sha1hash, keymat)
+ != SILC_SKE_STATUS_OK)
+ return FALSE;
+
+ if (!channel->private_keys)
+ channel->private_keys = silc_dlist_init();
+
+ /* Save the key */
+ entry = silc_calloc(1, sizeof(*entry));
+ entry->name = name ? strdup(name) : NULL;
+ entry->key = silc_memdup(keymat->send_enc_key, keymat->enc_key_len / 8);
+ entry->key_len = keymat->enc_key_len / 8;
+
+ /* Allocate the cipher and set the key*/
+ silc_cipher_alloc(cipher, &entry->cipher);
+ silc_cipher_set_key(entry->cipher, entry->key, keymat->enc_key_len);
+
+ /* Generate HMAC key from the channel key data and set it */
+ silc_hmac_alloc(hmac, NULL, &entry->hmac);
+ silc_hash_make(silc_hmac_get_hash(entry->hmac), entry->key,
+ entry->key_len, hash);
+ silc_hmac_set_key(entry->hmac, hash,
+ silc_hash_len(silc_hmac_get_hash(entry->hmac)));
+ memset(hash, 0, sizeof(hash));
+
+ /* Add to the private keys list */
+ silc_dlist_add(channel->private_keys, entry);
+
+ if (!channel->curr_key)
+ channel->curr_key = entry;
+
+ /* Free the key material */
+ silc_ske_free_key_material(keymat);
+
+ if (ret_key)
+ *ret_key = entry;