* silc_pkcs_load_private_key("privkey.pub", passphrase, passphrase_len,
* SILC_PKCS_SSH2, &public_key);
*
- * // Compute signature
- * silc_pkcs_sign(private_key, src, src_len, TRUE, sha1, rng, sign_cb, ctx);
+ * // Free public and private key. Frees automatically the underlaying SSH keys.
+ * silc_pkcs_public_key_free(public_key);
+ * silc_pkcs_private_key_free(private_key);
*
***/
#ifndef SILCSSH_H
*
* DESCRIPTION
*
- * SSH2 public and private key types. The default when new ke pair
+ * SSH2 public and private key types. The default when new key pair
* is created is SILC_SSH_KEY_OPENSSH.
*
* SOURCE
*
* This structure defines the SSH2 public key. This context can be
* retrieved from SilcPublicKey by calling silc_pkcs_public_key_get_pkcs
- * for the PKCS type SILC_PKCS_SSH2 type.
+ * for the PKCS type SILC_PKCS_SSH2.
*
* SOURCE
*/
*
* This structure defines the SSH2 private key. This context can be
* retrieved from SilcPrivateKey by calling silc_pkcs_private_key_get_pkcs
- * for the PKCS type SILC_PKCS_SSH2 type.
+ * for the PKCS type SILC_PKCS_SSH2.
*
* SOURCE
*/
* function. This function expects the public key to be in raw binary
* format, without any public key file markers or headers.
*
+ * This decodes SSH2 protocol compliant raw public key.
+ *
* This function returns the number of bytes decoded from the public
* key buffer or 0 on error.
*
* Encodes SSH Public key and returns the encoded buffer. Caller must
* free the returned buffer.
*
+ * This encodes SSH2 protocol compliant raw public key.
+ *
* If the `stack' is non-NULL the returned buffer is allocated from the
* `stack'. This call will consume `stack' so caller should push the stack
* before calling and then later pop it.
*
* DESCRIPTION
*
- * Frees the public key.
+ * Frees the public key. This need to be called only if you called
+ * silc_ssh_public_key_decode. SSH public keys allocated through the
+ * SILC PKCS API can be freed by calling silc_pkcs_public_key_free.
*
***/
void silc_ssh_public_key_free(SilcSshPublicKey public_key);
src, src_len, decrypt_cb, context);
}
+/* Sign context */
+typedef struct {
+ SilcSshPrivateKey privkey;
+ SilcPKCSSignCb sign_cb;
+ void *context;
+} *SilcSshSign;
+
+/* Sign callback. This formats the signature into SSH2 protocool compliant
+ format. */
+
+static void silc_pkcs_ssh_sign_cb(SilcBool success,
+ const unsigned char *signature,
+ SilcUInt32 signature_len,
+ void *context)
+{
+ SilcSshSign sign = context;
+ SilcBufferStruct sig;
+
+ memset(&sig, 0, sizeof(sig));
+ if (silc_buffer_format(&sig,
+ SILC_STR_UI_INT(7),
+ SILC_STR_UI32_STRING("ssh-"),
+ SILC_STR_UI32_STRING(sign->privkey->pkcs->name),
+ SILC_STR_UI_INT(signature_len),
+ SILC_STR_DATA(signature, signature_len),
+ SILC_STR_END) < 0) {
+ silc_free(sign);
+ sign->sign_cb(FALSE, NULL, 0, sign->context);
+ }
+
+ /* Deliver result */
+ sign->sign_cb(TRUE, silc_buffer_data(&sig), silc_buffer_len(&sig),
+ sign->context);
+
+ silc_buffer_purge(&sig);
+ silc_free(sign);
+}
+
/* Sign */
SILC_PKCS_SIGN(silc_pkcs_ssh_sign)
{
SilcSshPrivateKey privkey = private_key;
+ SilcSshSign sign;
if (!privkey->pkcs->sign) {
sign_cb(FALSE, NULL, 0, context);
return NULL;
}
+ sign = silc_calloc(1, sizeof(*sign));
+ if (!sign) {
+ sign_cb(FALSE, NULL, 0, context);
+ return NULL;
+ }
+
+ sign->privkey = privkey;
+ sign->sign_cb = sign_cb;
+ sign->context = context;
+
+ /* Sign. The callback will format it to SSH2 compliant format. */
return privkey->pkcs->sign(privkey->pkcs, privkey->private_key,
src, src_len,
compute_hash, hash, rng,
- sign_cb, context);
+ silc_pkcs_ssh_sign_cb, sign);
}
/* Verify */
SILC_PKCS_VERIFY(silc_pkcs_ssh_verify)
{
SilcSshPublicKey pubkey = public_key;
+ SilcBufferStruct sig;
if (!pubkey->pkcs->verify) {
verify_cb(FALSE, context);
return NULL;
}
+ /* Decode the SSH2 protocol style signature encoding. Ignore the
+ algorithm name. We know the algorithm. */
+ silc_buffer_set(&sig, signature, signature_len);
+ if (silc_buffer_unformat(&sig,
+ SILC_STR_UI32_NSTRING(NULL, NULL),
+ SILC_STR_UI32_NSTRING(&signature, &signature_len),
+ SILC_STR_END) < 0) {
+ verify_cb(FALSE, context);
+ return NULL;
+ }
+
+ /* Verify */
return pubkey->pkcs->verify(pubkey->pkcs, pubkey->public_key,
signature, signature_len,
data, data_len, hash, rng,