summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Schneider <asn@cryptomilk.org>2011-08-21 10:11:05 +0200
committerAndreas Schneider <asn@cryptomilk.org>2011-08-21 10:11:05 +0200
commit4f19a304d182ada3e67290c61bad47a0a6c16f5b (patch)
treed415688df25a60b2ce586e4120bfda5274226326
parentab0354dbb69aa6aa55427ccb8a6e696879b272cf (diff)
downloadlibssh-4f19a304d182ada3e67290c61bad47a0a6c16f5b.tar.gz
libssh-4f19a304d182ada3e67290c61bad47a0a6c16f5b.tar.xz
libssh-4f19a304d182ada3e67290c61bad47a0a6c16f5b.zip
pki: Add ssh_pki_export_signature_blob().
-rw-r--r--include/libssh/pki.h4
-rw-r--r--src/pki.c56
-rw-r--r--src/pki_crypto.c46
-rw-r--r--src/pki_gcrypt.c64
4 files changed, 170 insertions, 0 deletions
diff --git a/include/libssh/pki.h b/include/libssh/pki.h
index 6c009d5..dd090d6 100644
--- a/include/libssh/pki.h
+++ b/include/libssh/pki.h
@@ -91,6 +91,8 @@ int ssh_pki_import_pubkey_blob(const ssh_string key_blob,
ssh_string ssh_pki_export_pubkey_blob(const ssh_key key);
+int ssh_pki_export_signature_blob(const ssh_signature sign,
+ ssh_string *sign_blob);
ssh_string ssh_pki_do_sign(ssh_session session, ssh_buffer sigbuf,
ssh_key privatekey);
@@ -103,6 +105,8 @@ ssh_key pki_private_key_from_base64(const char *b64_key,
const char *passphrase,
ssh_auth_callback auth_fn,
void *auth_data);
+
+ssh_string pki_signature_to_blob(const ssh_signature sign);
struct signature_struct *pki_do_sign(const ssh_key privatekey,
const unsigned char *hash);
diff --git a/src/pki.c b/src/pki.c
index effeb70..f776938 100644
--- a/src/pki.c
+++ b/src/pki.c
@@ -857,6 +857,62 @@ int ssh_pki_export_pubkey_file(const ssh_key key,
return SSH_OK;
}
+int ssh_pki_export_signature_blob(const ssh_signature sig,
+ ssh_string *sig_blob)
+{
+ ssh_buffer buf = NULL;
+ ssh_string str;
+ int rc;
+
+ if (sig == NULL || sig_blob == NULL) {
+ return SSH_ERROR;
+ }
+
+ buf = ssh_buffer_new();
+ if (buf == NULL) {
+ return SSH_ERROR;
+ }
+
+ str = ssh_string_from_char(ssh_key_type_to_char(sig->type));
+ if (str == NULL) {
+ ssh_buffer_free(buf);
+ return SSH_ERROR;
+ }
+
+ rc = buffer_add_ssh_string(buf, str);
+ ssh_string_free(str);
+ if (rc < 0) {
+ ssh_buffer_free(buf);
+ return SSH_ERROR;
+ }
+
+ str = pki_signature_to_blob(sig);
+ if (str == NULL) {
+ ssh_buffer_free(buf);
+ return SSH_ERROR;
+ }
+
+ rc = buffer_add_ssh_string(buf, str);
+ ssh_string_free(str);
+ if (rc < 0) {
+ ssh_buffer_free(buf);
+ return SSH_ERROR;
+ }
+
+ str = ssh_string_new(buffer_get_rest_len(buf));
+ if (str == NULL) {
+ ssh_buffer_free(buf);
+ return SSH_ERROR;
+ }
+
+ ssh_string_fill(str, buffer_get_rest(buf), buffer_get_rest_len(buf));
+ ssh_buffer_free(buf);
+
+ *sig_blob = str;
+
+ return SSH_OK;
+}
+
/*
* This function signs the session id (known as H) as a string then
* the content of sigbuf */
diff --git a/src/pki_crypto.c b/src/pki_crypto.c
index 0309427..0dafd22 100644
--- a/src/pki_crypto.c
+++ b/src/pki_crypto.c
@@ -515,6 +515,52 @@ static ssh_string _RSA_do_sign(const unsigned char *payload,
return sign;
}
+ssh_string pki_signature_to_blob(const ssh_signature sig)
+{
+ char buffer[40] = {0};
+ ssh_string sig_blob;
+ ssh_string r;
+ ssh_string s;
+
+ switch(sig->type) {
+ case SSH_KEYTYPE_DSS:
+ r = make_bignum_string(sig->dsa_sig->r);
+ if (r == NULL) {
+ return NULL;
+ }
+ s = make_bignum_string(sig->dsa_sig->s);
+ if (s == NULL) {
+ ssh_string_free(r);
+ return NULL;
+ }
+
+ memcpy(buffer,
+ ((char *)ssh_string_data(r)) + ssh_string_len(r) - 20,
+ 20);
+ memcpy(buffer + 20,
+ ((char *)ssh_string_data(s)) + ssh_string_len(s) - 20,
+ 20);
+
+ ssh_string_free(r);
+ ssh_string_free(s);
+
+ sig_blob = ssh_string_new(40);
+ if (sig_blob == NULL) {
+ return NULL;
+ }
+
+ ssh_string_fill(sig_blob, buffer, 40);
+ case SSH_KEYTYPE_RSA:
+ case SSH_KEYTYPE_RSA1:
+ sig_blob = string_copy(sig->rsa_sig);
+ case SSH_KEYTYPE_ECDSA:
+ case SSH_KEYTYPE_UNKNOWN:
+ break;
+ }
+
+ return sig_blob;
+}
+
struct signature_struct *pki_do_sign(ssh_key privatekey,
const unsigned char *hash) {
struct signature_struct *sign;
diff --git a/src/pki_gcrypt.c b/src/pki_gcrypt.c
index 5e8223f..2a6a120 100644
--- a/src/pki_gcrypt.c
+++ b/src/pki_gcrypt.c
@@ -1160,6 +1160,70 @@ fail:
return NULL;
}
+ssh_string pki_signature_to_blob(const ssh_signature sig)
+{
+ char buffer[40] = {0};
+ const char *r = NULL;
+ const char *s = NULL;
+ gcry_sexp_t sexp;
+ size_t size = 0;
+ ssh_string sig_blob;
+
+ switch(sig->type) {
+ case SSH_KEYTYPE_DSS:
+ sexp = gcry_sexp_find_token(sig->dsa_sig, "r", 0);
+ if (sexp == NULL) {
+ return NULL;
+ }
+ r = gcry_sexp_nth_data(sexp, 1, &size);
+ /* libgcrypt put 0 when first bit is set */
+ if (*r == 0) {
+ size--;
+ r++;
+ }
+ memcpy(buffer, r + size - 20, 20);
+ gcry_sexp_release(sexp);
+
+ sexp = gcry_sexp_find_token(sig->dsa_sig, "s", 0);
+ if (sexp == NULL) {
+ return NULL;
+ }
+ s = gcry_sexp_nth_data(sexp,1,&size);
+ if (*s == 0) {
+ size--;
+ s++;
+ }
+ memcpy(buffer+ 20, s + size - 20, 20);
+ gcry_sexp_release(sexp);
+ break;
+ case SSH_KEYTYPE_RSA:
+ case SSH_KEYTYPE_RSA1:
+ sexp = gcry_sexp_find_token(sig->rsa_sig, "s", 0);
+ if (sexp == NULL) {
+ return NULL;
+ }
+ s = gcry_sexp_nth_data(sexp, 1, &size);
+ if (*s == 0) {
+ size--;
+ s++;
+ }
+
+ sig_blob = ssh_string_new(size);
+ if (sig_blob == NULL) {
+ return NULL;
+ }
+ ssh_string_fill(sig_blob, discard_const_p(char, s), size);
+
+ gcry_sexp_release(sexp);
+ break;
+ case SSH_KEYTYPE_ECDSA:
+ case SSH_KEYTYPE_UNKNOWN:
+ break;
+ }
+
+ return sig_blob;
+}
+
struct signature_struct *pki_do_sign(ssh_key privatekey,
const unsigned char *hash) {
struct signature_struct *sign;