aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Schneider <asn@cryptomilk.org>2011-08-21 11:03:53 +0200
committerAndreas Schneider <asn@cryptomilk.org>2011-08-21 11:03:53 +0200
commita4b2518761c6b68b8a28ea250d58e7257bce6554 (patch)
tree2f81d30583ae47854779e9d914e6104c09ef8e8c
parent4f19a304d182ada3e67290c61bad47a0a6c16f5b (diff)
downloadlibssh-a4b2518761c6b68b8a28ea250d58e7257bce6554.tar.gz
libssh-a4b2518761c6b68b8a28ea250d58e7257bce6554.tar.xz
libssh-a4b2518761c6b68b8a28ea250d58e7257bce6554.zip
pki: Add ssh_pki_import_signature_blob().
-rw-r--r--include/libssh/pki.h6
-rw-r--r--src/pki.c60
-rw-r--r--src/pki_crypto.c104
-rw-r--r--src/pki_gcrypt.c80
4 files changed, 250 insertions, 0 deletions
diff --git a/include/libssh/pki.h b/include/libssh/pki.h
index dd090d6..b0f682b 100644
--- a/include/libssh/pki.h
+++ b/include/libssh/pki.h
@@ -93,6 +93,9 @@ 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);
+int ssh_pki_import_signature_blob(const ssh_string sig_blob,
+ const ssh_key pubkey,
+ ssh_signature *psig);
ssh_string ssh_pki_do_sign(ssh_session session, ssh_buffer sigbuf,
ssh_key privatekey);
@@ -107,6 +110,9 @@ ssh_key pki_private_key_from_base64(const char *b64_key,
void *auth_data);
ssh_string pki_signature_to_blob(const ssh_signature sign);
+ssh_signature pki_signature_from_blob(const ssh_key pubkey,
+ const ssh_string sig_blob,
+ enum ssh_keytypes_e type);
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 f776938..542bede 100644
--- a/src/pki.c
+++ b/src/pki.c
@@ -913,6 +913,66 @@ int ssh_pki_export_signature_blob(const ssh_signature sig,
return SSH_OK;
}
+int ssh_pki_import_signature_blob(const ssh_string sig_blob,
+ const ssh_key pubkey,
+ ssh_signature *psig)
+{
+ ssh_signature sig;
+ enum ssh_keytypes_e type;
+ ssh_string str;
+ ssh_buffer buf;
+ char *type_c;
+ int rc;
+
+ if (sig_blob == NULL || psig == NULL) {
+ return SSH_ERROR;
+ }
+
+ buf = ssh_buffer_new();
+ if (buf == NULL) {
+ return SSH_ERROR;
+ }
+
+ rc = buffer_add_data(buf,
+ ssh_string_data(sig_blob),
+ ssh_string_len(sig_blob));
+ if (rc < 0) {
+ ssh_buffer_free(buf);
+ return SSH_ERROR;
+ }
+
+ str = buffer_get_ssh_string(buf);
+ if (str == NULL) {
+ ssh_buffer_free(buf);
+ return SSH_ERROR;
+ }
+
+ type_c = ssh_string_to_char(str);
+ ssh_string_free(str);
+ if (type_c == NULL) {
+ ssh_buffer_free(buf);
+ return SSH_ERROR;
+ }
+
+ type = ssh_key_type_from_name(type_c);
+ SAFE_FREE(type_c);
+
+ str = buffer_get_ssh_string(buf);
+ ssh_buffer_free(buf);
+ if (str == NULL) {
+ return SSH_ERROR;
+ }
+
+ sig = pki_signature_from_blob(pubkey, str, type);
+ ssh_string_free(str);
+ if (sig == NULL) {
+ return SSH_ERROR;
+ }
+
+ *psig = sig;
+ 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 0dafd22..f71c22b 100644
--- a/src/pki_crypto.c
+++ b/src/pki_crypto.c
@@ -561,6 +561,110 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
return sig_blob;
}
+ssh_signature pki_signature_from_blob(const ssh_key pubkey,
+ const ssh_string sig_blob,
+ enum ssh_keytypes_e type)
+{
+ ssh_signature sig;
+ ssh_string r;
+ ssh_string s;
+ size_t len;
+ size_t rsalen;
+
+ sig = ssh_signature_new();
+ if (sig == NULL) {
+ return NULL;
+ }
+
+ sig->type = type;
+
+ len = ssh_string_len(sig_blob);
+
+ switch(type) {
+ case SSH_KEYTYPE_DSS:
+ /* 40 is the dual signature blob len. */
+ if (len != 40) {
+ ssh_pki_log("Signature has wrong size: %lu",
+ (unsigned long)len);
+ ssh_signature_free(sig);
+ return NULL;
+ }
+
+#ifdef DEBUG_CRYPTO
+ ssh_print_hexa("r", ssh_string_data(str), 20);
+ ssh_print_hexa("s", (unsigned char *)ssh_string_data(rs) + 20, 20);
+#endif
+
+ sig->dsa_sig = DSA_SIG_new();
+ if (sig->dsa_sig == NULL) {
+ ssh_signature_free(sig);
+ return NULL;
+ }
+
+ r = ssh_string_new(20);
+ if (r == NULL) {
+ ssh_signature_free(sig);
+ return NULL;
+ }
+ ssh_string_fill(r, ssh_string_data(sig_blob), 20);
+
+ sig->dsa_sig->r = make_string_bn(r);
+ ssh_string_free(r);
+ if (sig->dsa_sig->r == NULL) {
+ ssh_signature_free(sig);
+ return NULL;
+ }
+
+ s = ssh_string_new(20);
+ if (s == NULL) {
+ ssh_signature_free(sig);
+ return NULL;
+ }
+ ssh_string_fill(s, (char *)ssh_string_data(sig_blob) + 20, 20);
+
+ sig->dsa_sig->s = make_string_bn(s);
+ ssh_string_free(s);
+ if (sig->dsa_sig->s == NULL) {
+ ssh_signature_free(sig);
+ return NULL;
+ }
+
+ break;
+ case SSH_KEYTYPE_RSA:
+ case SSH_KEYTYPE_RSA1:
+ rsalen = RSA_size(pubkey->rsa);
+
+ if (len > rsalen) {
+ ssh_pki_log("Signature is to big size: %lu",
+ (unsigned long)len);
+ ssh_signature_free(sig);
+ return NULL;
+ }
+
+ if (len < rsalen) {
+ ssh_pki_log("RSA signature len %lu < %lu",
+ (unsigned long)len, (unsigned long)rsalen);
+ }
+
+#ifdef DEBUG_CRYPTO
+ ssh_pki_log("RSA signature len: %lu", (unsigned long)len);
+ ssh_print_hexa("RSA signature", ssh_string_data(sig_blob), len);
+#endif
+ sig->rsa_sig = string_copy(sig_blob);
+ if (sig->rsa_sig == NULL) {
+ ssh_signature_free(sig);
+ return NULL;
+ }
+ break;
+ case SSH_KEYTYPE_ECDSA:
+ case SSH_KEYTYPE_UNKNOWN:
+ ssh_pki_log("Unknown signature type");
+ return NULL;
+ }
+
+ return sig;
+}
+
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 2a6a120..3317514 100644
--- a/src/pki_gcrypt.c
+++ b/src/pki_gcrypt.c
@@ -1224,6 +1224,86 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
return sig_blob;
}
+ssh_signature pki_signature_from_blob(const ssh_key pubkey,
+ const ssh_string sig_blob,
+ enum ssh_keytypes_e type)
+{
+ ssh_signature sig;
+ gcry_error_t err;
+ size_t len;
+ size_t rsalen;
+
+ sig = ssh_signature_new();
+ if (sig == NULL) {
+ return NULL;
+ }
+
+ sig->type = type;
+
+ len = ssh_string_len(sig_blob);
+
+ switch(type) {
+ case SSH_KEYTYPE_DSS:
+ /* 40 is the dual signature blob len. */
+ if (len != 40) {
+ ssh_pki_log("Signature has wrong size: %lu",
+ (unsigned long)len);
+ ssh_signature_free(sig);
+ return NULL;
+ }
+
+#ifdef DEBUG_CRYPTO
+ ssh_print_hexa("r", ssh_string_data(str), 20);
+ ssh_print_hexa("s", (unsigned char *)ssh_string_data(rs) + 20, 20);
+#endif
+
+ err = gcry_sexp_build(&sig->dsa_sig,
+ NULL,
+ "(sig-val(dsa(r %b)(s %b)))",
+ 20,
+ ssh_string_data(sig_blob),
+ 20,
+ (unsigned char *)ssh_string_data(sig_blob) + 20);
+ if (err) {
+ ssh_signature_free(sig);
+ return NULL;
+ }
+ break;
+ case SSH_KEYTYPE_RSA:
+ case SSH_KEYTYPE_RSA1:
+ rsalen = (gcry_pk_get_nbits(pubkey->rsa) + 7) / 8;
+
+ if (len > rsalen) {
+ ssh_pki_log("Signature is to big size: %lu",
+ (unsigned long)len);
+ ssh_signature_free(sig);
+ return NULL;
+ }
+
+ if (len < rsalen) {
+ ssh_pki_log("RSA signature len %lu < %lu",
+ (unsigned long)len, (unsigned long)rsalen);
+ }
+
+#ifdef DEBUG_CRYPTO
+ ssh_pki_log("RSA signature len: %lu", (unsigned long)len);
+ ssh_print_hexa("RSA signature", ssh_string_data(sig_blob), len);
+#endif
+
+ if (gcry_sexp_build(&sig->rsa_sig, NULL, "(sig-val(rsa(s %b)))",
+ ssh_string_len(sig_blob), ssh_string_data(sig_blob))) {
+ ssh_signature_free(sig);
+ return NULL;
+ }
+ case SSH_KEYTYPE_ECDSA:
+ case SSH_KEYTYPE_UNKNOWN:
+ ssh_pki_log("Unknown signature type");
+ return NULL;
+ }
+
+ return sig;
+}
+
struct signature_struct *pki_do_sign(ssh_key privatekey,
const unsigned char *hash) {
struct signature_struct *sign;