diff options
author | Andreas Schneider <asn@cryptomilk.org> | 2011-08-21 10:11:05 +0200 |
---|---|---|
committer | Andreas Schneider <asn@cryptomilk.org> | 2011-08-21 10:11:05 +0200 |
commit | 4f19a304d182ada3e67290c61bad47a0a6c16f5b (patch) | |
tree | d415688df25a60b2ce586e4120bfda5274226326 | |
parent | ab0354dbb69aa6aa55427ccb8a6e696879b272cf (diff) | |
download | libssh-4f19a304d182ada3e67290c61bad47a0a6c16f5b.tar.gz libssh-4f19a304d182ada3e67290c61bad47a0a6c16f5b.tar.xz libssh-4f19a304d182ada3e67290c61bad47a0a6c16f5b.zip |
pki: Add ssh_pki_export_signature_blob().
-rw-r--r-- | include/libssh/pki.h | 4 | ||||
-rw-r--r-- | src/pki.c | 56 | ||||
-rw-r--r-- | src/pki_crypto.c | 46 | ||||
-rw-r--r-- | src/pki_gcrypt.c | 64 |
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); @@ -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; |