diff options
Diffstat (limited to 'libssh/src/pki_gcrypt.c')
-rw-r--r-- | libssh/src/pki_gcrypt.c | 1713 |
1 files changed, 0 insertions, 1713 deletions
diff --git a/libssh/src/pki_gcrypt.c b/libssh/src/pki_gcrypt.c deleted file mode 100644 index 2811acce..00000000 --- a/libssh/src/pki_gcrypt.c +++ /dev/null @@ -1,1713 +0,0 @@ -/* - * pki_gcrypt.c private and public key handling using gcrypt. - * - * This file is part of the SSH Library - * - * Copyright (c) 2003-2009 Aris Adamantiadis - * Copyright (c) 2009-2011 Andreas Schneider <asn@cryptomilk.org> - * - * The SSH Library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at your - * option) any later version. - * - * The SSH Library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with the SSH Library; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -#include "config.h" - -#ifdef HAVE_LIBGCRYPT - -#include <string.h> -#include <stdlib.h> -#include <gcrypt.h> -#include <stdio.h> - -#include "libssh/priv.h" -#include "libssh/buffer.h" -#include "libssh/session.h" -#include "libssh/wrapper.h" -#include "libssh/misc.h" -#include "libssh/pki.h" -#include "libssh/pki_priv.h" - -#define MAXLINESIZE 80 -#define RSA_HEADER_BEGIN "-----BEGIN RSA PRIVATE KEY-----" -#define RSA_HEADER_END "-----END RSA PRIVATE KEY-----" -#define DSA_HEADER_BEGIN "-----BEGIN DSA PRIVATE KEY-----" -#define DSA_HEADER_END "-----END DSA PRIVATE KEY-----" - -#define MAX_KEY_SIZE 32 -#define MAX_PASSPHRASE_SIZE 1024 -#define ASN1_INTEGER 2 -#define ASN1_SEQUENCE 48 -#define PKCS5_SALT_LEN 8 - -static int load_iv(const char *header, unsigned char *iv, int iv_len) { - int i; - int j; - int k; - - memset(iv, 0, iv_len); - for (i = 0; i < iv_len; i++) { - if ((header[2*i] >= '0') && (header[2*i] <= '9')) - j = header[2*i] - '0'; - else if ((header[2*i] >= 'A') && (header[2*i] <= 'F')) - j = header[2*i] - 'A' + 10; - else if ((header[2*i] >= 'a') && (header[2*i] <= 'f')) - j = header[2*i] - 'a' + 10; - else - return -1; - if ((header[2*i+1] >= '0') && (header[2*i+1] <= '9')) - k = header[2*i+1] - '0'; - else if ((header[2*i+1] >= 'A') && (header[2*i+1] <= 'F')) - k = header[2*i+1] - 'A' + 10; - else if ((header[2*i+1] >= 'a') && (header[2*i+1] <= 'f')) - k = header[2*i+1] - 'a' + 10; - else - return -1; - iv[i] = (j << 4) + k; - } - return 0; -} - -static uint32_t char_to_u32(unsigned char *data, uint32_t size) { - uint32_t ret; - uint32_t i; - - for (i = 0, ret = 0; i < size; ret = ret << 8, ret += data[i++]) - ; - return ret; -} - -static uint32_t asn1_get_len(ssh_buffer buffer) { - uint32_t len; - unsigned char tmp[4]; - - if (buffer_get_data(buffer,tmp,1) == 0) { - return 0; - } - - if (tmp[0] > 127) { - len = tmp[0] & 127; - if (len > 4) { - return 0; /* Length doesn't fit in u32. Can this really happen? */ - } - if (buffer_get_data(buffer,tmp,len) == 0) { - return 0; - } - len = char_to_u32(tmp, len); - } else { - len = char_to_u32(tmp, 1); - } - - return len; -} - -static ssh_string asn1_get_int(ssh_buffer buffer) { - ssh_string str; - unsigned char type; - uint32_t size; - - if (buffer_get_data(buffer, &type, 1) == 0 || type != ASN1_INTEGER) { - return NULL; - } - size = asn1_get_len(buffer); - if (size == 0) { - return NULL; - } - - str = ssh_string_new(size); - if (str == NULL) { - return NULL; - } - - if (buffer_get_data(buffer, ssh_string_data(str), size) == 0) { - ssh_string_free(str); - return NULL; - } - - return str; -} - -static int asn1_check_sequence(ssh_buffer buffer) { - unsigned char *j = NULL; - unsigned char tmp; - int i; - uint32_t size; - uint32_t padding; - - if (buffer_get_data(buffer, &tmp, 1) == 0 || tmp != ASN1_SEQUENCE) { - return 0; - } - - size = asn1_get_len(buffer); - if ((padding = ssh_buffer_get_len(buffer) - buffer->pos - size) > 0) { - for (i = ssh_buffer_get_len(buffer) - buffer->pos - size, - j = (unsigned char*)ssh_buffer_get_begin(buffer) + size + buffer->pos; - i; - i--, j++) - { - if (*j != padding) { /* padding is allowed */ - return 0; /* but nothing else */ - } - } - } - - return 1; -} - -static int passphrase_to_key(char *data, unsigned int datalen, - unsigned char *salt, unsigned char *key, unsigned int keylen) { - MD5CTX md; - unsigned char digest[MD5_DIGEST_LEN] = {0}; - unsigned int i; - unsigned int j; - unsigned int md_not_empty; - - for (j = 0, md_not_empty = 0; j < keylen; ) { - md = md5_init(); - if (md == NULL) { - return -1; - } - - if (md_not_empty) { - md5_update(md, digest, MD5_DIGEST_LEN); - } else { - md_not_empty = 1; - } - - md5_update(md, data, datalen); - if (salt) { - md5_update(md, salt, PKCS5_SALT_LEN); - } - md5_final(digest, md); - - for (i = 0; j < keylen && i < MD5_DIGEST_LEN; j++, i++) { - if (key) { - key[j] = digest[i]; - } - } - } - - return 0; -} - -static int privatekey_decrypt(int algo, int mode, unsigned int key_len, - unsigned char *iv, unsigned int iv_len, - ssh_buffer data, ssh_auth_callback cb, - void *userdata, - const char *desc) -{ - char passphrase[MAX_PASSPHRASE_SIZE] = {0}; - unsigned char key[MAX_KEY_SIZE] = {0}; - unsigned char *tmp = NULL; - gcry_cipher_hd_t cipher; - int rc = -1; - - if (!algo) { - return -1; - } - - if (cb) { - rc = (*cb)(desc, passphrase, MAX_PASSPHRASE_SIZE, 0, 0, userdata); - if (rc < 0) { - return -1; - } - } else if (cb == NULL && userdata != NULL) { - snprintf(passphrase, MAX_PASSPHRASE_SIZE, "%s", (char *) userdata); - } - - if (passphrase_to_key(passphrase, strlen(passphrase), iv, key, key_len) < 0) { - return -1; - } - - if (gcry_cipher_open(&cipher, algo, mode, 0) - || gcry_cipher_setkey(cipher, key, key_len) - || gcry_cipher_setiv(cipher, iv, iv_len) - || (tmp = malloc(ssh_buffer_get_len(data) * sizeof (char))) == NULL - || gcry_cipher_decrypt(cipher, tmp, ssh_buffer_get_len(data), - ssh_buffer_get_begin(data), ssh_buffer_get_len(data))) { - gcry_cipher_close(cipher); - return -1; - } - - memcpy(ssh_buffer_get_begin(data), tmp, ssh_buffer_get_len(data)); - - SAFE_FREE(tmp); - gcry_cipher_close(cipher); - - return 0; -} - -static int privatekey_dek_header(const char *header, unsigned int header_len, - int *algo, int *mode, unsigned int *key_len, unsigned char **iv, - unsigned int *iv_len) { - unsigned int iv_pos; - - if (header_len > 13 && !strncmp("DES-EDE3-CBC", header, 12)) - { - *algo = GCRY_CIPHER_3DES; - iv_pos = 13; - *mode = GCRY_CIPHER_MODE_CBC; - *key_len = 24; - *iv_len = 8; - } - else if (header_len > 8 && !strncmp("DES-CBC", header, 7)) - { - *algo = GCRY_CIPHER_DES; - iv_pos = 8; - *mode = GCRY_CIPHER_MODE_CBC; - *key_len = 8; - *iv_len = 8; - } - else if (header_len > 12 && !strncmp("AES-128-CBC", header, 11)) - { - *algo = GCRY_CIPHER_AES128; - iv_pos = 12; - *mode = GCRY_CIPHER_MODE_CBC; - *key_len = 16; - *iv_len = 16; - } - else if (header_len > 12 && !strncmp("AES-192-CBC", header, 11)) - { - *algo = GCRY_CIPHER_AES192; - iv_pos = 12; - *mode = GCRY_CIPHER_MODE_CBC; - *key_len = 24; - *iv_len = 16; - } - else if (header_len > 12 && !strncmp("AES-256-CBC", header, 11)) - { - *algo = GCRY_CIPHER_AES256; - iv_pos = 12; - *mode = GCRY_CIPHER_MODE_CBC; - *key_len = 32; - *iv_len = 16; - } else { - return -1; - } - - *iv = malloc(*iv_len); - if (*iv == NULL) { - return -1; - } - - return load_iv(header + iv_pos, *iv, *iv_len); -} - -#define get_next_line(p, len) { \ - while(p[len] == '\n' || p[len] == '\r') /* skip empty lines */ \ - len++; \ - if(p[len] == '\0') /* EOL */ \ - len = -1; \ - else /* calculate length */ \ - for(p += len, len = 0; p[len] && p[len] != '\n' \ - && p[len] != '\r'; len++); \ - } - -static ssh_buffer privatekey_string_to_buffer(const char *pkey, int type, - ssh_auth_callback cb, void *userdata, const char *desc) { - ssh_buffer buffer = NULL; - ssh_buffer out = NULL; - const char *p; - unsigned char *iv = NULL; - const char *header_begin; - const char *header_end; - unsigned int header_begin_size; - unsigned int header_end_size; - unsigned int key_len = 0; - unsigned int iv_len = 0; - int algo = 0; - int mode = 0; - int len; - - buffer = ssh_buffer_new(); - if (buffer == NULL) { - return NULL; - } - - switch(type) { - case SSH_KEYTYPE_DSS: - header_begin = DSA_HEADER_BEGIN; - header_end = DSA_HEADER_END; - break; - case SSH_KEYTYPE_RSA: - header_begin = RSA_HEADER_BEGIN; - header_end = RSA_HEADER_END; - break; - default: - ssh_buffer_free(buffer); - return NULL; - } - - header_begin_size = strlen(header_begin); - header_end_size = strlen(header_end); - - p = pkey; - len = 0; - get_next_line(p, len); - - while(len > 0 && strncmp(p, header_begin, header_begin_size)) { - /* skip line */ - get_next_line(p, len); - } - if(len < 0) { - /* no header found */ - return NULL; - } - /* skip header line */ - get_next_line(p, len); - - if (len > 11 && strncmp("Proc-Type: 4,ENCRYPTED", p, 11) == 0) { - /* skip line */ - get_next_line(p, len); - - if (len > 10 && strncmp("DEK-Info: ", p, 10) == 0) { - p += 10; - len = 0; - get_next_line(p, len); - if (privatekey_dek_header(p, len, &algo, &mode, &key_len, - &iv, &iv_len) < 0) { - ssh_buffer_free(buffer); - SAFE_FREE(iv); - return NULL; - } - } else { - ssh_buffer_free(buffer); - SAFE_FREE(iv); - return NULL; - } - } else { - if(len > 0) { - if (ssh_buffer_add_data(buffer, p, len) < 0) { - ssh_buffer_free(buffer); - SAFE_FREE(iv); - return NULL; - } - } - } - - get_next_line(p, len); - while(len > 0 && strncmp(p, header_end, header_end_size) != 0) { - if (ssh_buffer_add_data(buffer, p, len) < 0) { - ssh_buffer_free(buffer); - SAFE_FREE(iv); - return NULL; - } - get_next_line(p, len); - } - - if (len == -1 || strncmp(p, header_end, header_end_size) != 0) { - ssh_buffer_free(buffer); - SAFE_FREE(iv); - return NULL; - } - - if (ssh_buffer_add_data(buffer, "\0", 1) < 0) { - ssh_buffer_free(buffer); - SAFE_FREE(iv); - return NULL; - } - - out = base64_to_bin(ssh_buffer_get_begin(buffer)); - ssh_buffer_free(buffer); - if (out == NULL) { - SAFE_FREE(iv); - return NULL; - } - - if (algo) { - if (privatekey_decrypt(algo, mode, key_len, iv, iv_len, out, - cb, userdata, desc) < 0) { - ssh_buffer_free(out); - SAFE_FREE(iv); - return NULL; - } - } - SAFE_FREE(iv); - - return out; -} - -static int b64decode_rsa_privatekey(const char *pkey, gcry_sexp_t *r, - ssh_auth_callback cb, void *userdata, const char *desc) { - const unsigned char *data; - ssh_string n = NULL; - ssh_string e = NULL; - ssh_string d = NULL; - ssh_string p = NULL; - ssh_string q = NULL; - ssh_string unused1 = NULL; - ssh_string unused2 = NULL; - ssh_string u = NULL; - ssh_string v = NULL; - ssh_buffer buffer = NULL; - int rc = 1; - - buffer = privatekey_string_to_buffer(pkey, SSH_KEYTYPE_RSA, cb, userdata, desc); - if (buffer == NULL) { - return 0; - } - - if (!asn1_check_sequence(buffer)) { - ssh_buffer_free(buffer); - return 0; - } - - v = asn1_get_int(buffer); - if (v == NULL) { - ssh_buffer_free(buffer); - return 0; - } - - data = ssh_string_data(v); - if (ssh_string_len(v) != 1 || data[0] != 0) { - ssh_buffer_free(buffer); - return 0; - } - - n = asn1_get_int(buffer); - e = asn1_get_int(buffer); - d = asn1_get_int(buffer); - q = asn1_get_int(buffer); - p = asn1_get_int(buffer); - unused1 = asn1_get_int(buffer); - unused2 = asn1_get_int(buffer); - u = asn1_get_int(buffer); - - ssh_buffer_free(buffer); - - if (n == NULL || e == NULL || d == NULL || p == NULL || q == NULL || - unused1 == NULL || unused2 == NULL|| u == NULL) { - rc = 0; - goto error; - } - - if (gcry_sexp_build(r, NULL, - "(private-key(rsa(n %b)(e %b)(d %b)(p %b)(q %b)(u %b)))", - ssh_string_len(n), ssh_string_data(n), - ssh_string_len(e), ssh_string_data(e), - ssh_string_len(d), ssh_string_data(d), - ssh_string_len(p), ssh_string_data(p), - ssh_string_len(q), ssh_string_data(q), - ssh_string_len(u), ssh_string_data(u))) { - rc = 0; - } - -error: - ssh_string_free(n); - ssh_string_free(e); - ssh_string_free(d); - ssh_string_free(p); - ssh_string_free(q); - ssh_string_free(unused1); - ssh_string_free(unused2); - ssh_string_free(u); - ssh_string_free(v); - - return rc; -} - -static int b64decode_dsa_privatekey(const char *pkey, gcry_sexp_t *r, ssh_auth_callback cb, - void *userdata, const char *desc) { - const unsigned char *data; - ssh_buffer buffer = NULL; - ssh_string p = NULL; - ssh_string q = NULL; - ssh_string g = NULL; - ssh_string y = NULL; - ssh_string x = NULL; - ssh_string v = NULL; - int rc = 1; - - buffer = privatekey_string_to_buffer(pkey, SSH_KEYTYPE_DSS, cb, userdata, desc); - if (buffer == NULL) { - return 0; - } - - if (!asn1_check_sequence(buffer)) { - ssh_buffer_free(buffer); - return 0; - } - - v = asn1_get_int(buffer); - if (v == NULL) { - ssh_buffer_free(buffer); - return 0; - } - - data = ssh_string_data(v); - if (ssh_string_len(v) != 1 || data[0] != 0) { - ssh_buffer_free(buffer); - return 0; - } - - p = asn1_get_int(buffer); - q = asn1_get_int(buffer); - g = asn1_get_int(buffer); - y = asn1_get_int(buffer); - x = asn1_get_int(buffer); - ssh_buffer_free(buffer); - - if (p == NULL || q == NULL || g == NULL || y == NULL || x == NULL) { - rc = 0; - goto error; - } - - if (gcry_sexp_build(r, NULL, - "(private-key(dsa(p %b)(q %b)(g %b)(y %b)(x %b)))", - ssh_string_len(p), ssh_string_data(p), - ssh_string_len(q), ssh_string_data(q), - ssh_string_len(g), ssh_string_data(g), - ssh_string_len(y), ssh_string_data(y), - ssh_string_len(x), ssh_string_data(x))) { - rc = 0; - } - -error: - ssh_string_free(p); - ssh_string_free(q); - ssh_string_free(g); - ssh_string_free(y); - ssh_string_free(x); - ssh_string_free(v); - - return rc; -} - -#ifdef HAVE_GCRYPT_ECC -int pki_key_ecdsa_nid_from_name(const char *name) -{ - return -1; -} -#endif - -ssh_string pki_private_key_to_pem(const ssh_key key, - const char *passphrase, - ssh_auth_callback auth_fn, - void *auth_data) -{ - (void) key; - (void) passphrase; - (void) auth_fn; - (void) auth_data; - - return NULL; -} - -ssh_key pki_private_key_from_base64(const char *b64_key, - const char *passphrase, - ssh_auth_callback auth_fn, - void *auth_data) -{ - gcry_sexp_t dsa = NULL; - gcry_sexp_t rsa = NULL; - ssh_key key = NULL; - enum ssh_keytypes_e type; - int valid; - - /* needed for gcrypt initialization */ - if (ssh_init() < 0) { - return NULL; - } - - type = pki_privatekey_type_from_string(b64_key); - if (type == SSH_KEYTYPE_UNKNOWN) { - ssh_pki_log("Unknown or invalid private key."); - return NULL; - } - - switch (type) { - case SSH_KEYTYPE_DSS: - if (passphrase == NULL) { - if (auth_fn) { - valid = b64decode_dsa_privatekey(b64_key, &dsa, auth_fn, - auth_data, "Passphrase for private key:"); - } else { - valid = b64decode_dsa_privatekey(b64_key, &dsa, NULL, NULL, - NULL); - } - } else { - valid = b64decode_dsa_privatekey(b64_key, &dsa, NULL, (void *) - passphrase, NULL); - } - - if (!valid) { - ssh_pki_log("Parsing private key"); - goto fail; - } - break; - case SSH_KEYTYPE_RSA: - case SSH_KEYTYPE_RSA1: - if (passphrase == NULL) { - if (auth_fn) { - valid = b64decode_rsa_privatekey(b64_key, &rsa, auth_fn, - auth_data, "Passphrase for private key:"); - } else { - valid = b64decode_rsa_privatekey(b64_key, &rsa, NULL, NULL, - NULL); - } - } else { - valid = b64decode_rsa_privatekey(b64_key, &rsa, NULL, - (void *)passphrase, NULL); - } - - if (!valid) { - ssh_pki_log("Parsing private key"); - goto fail; - } - break; - case SSH_KEYTYPE_ECDSA: - case SSH_KEYTYPE_UNKNOWN: - ssh_pki_log("Unkown or invalid private key type %d", type); - return NULL; - } - - key = ssh_key_new(); - if (key == NULL) { - goto fail; - } - - key->type = type; - key->type_c = ssh_key_type_to_char(type); - key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC; - key->dsa = dsa; - key->rsa = rsa; - - return key; -fail: - ssh_key_free(key); - gcry_sexp_release(dsa); - gcry_sexp_release(rsa); - - return NULL; -} - -int pki_pubkey_build_dss(ssh_key key, - ssh_string p, - ssh_string q, - ssh_string g, - ssh_string pubkey) { - gcry_sexp_build(&key->dsa, NULL, - "(public-key(dsa(p %b)(q %b)(g %b)(y %b)))", - ssh_string_len(p), ssh_string_data(p), - ssh_string_len(q), ssh_string_data(q), - ssh_string_len(g), ssh_string_data(g), - ssh_string_len(pubkey), ssh_string_data(pubkey)); - if (key->dsa == NULL) { - return SSH_ERROR; - } - - return SSH_OK; -} - -int pki_pubkey_build_rsa(ssh_key key, - ssh_string e, - ssh_string n) { - gcry_sexp_build(&key->rsa, NULL, - "(public-key(rsa(n %b)(e %b)))", - ssh_string_len(n), ssh_string_data(n), - ssh_string_len(e),ssh_string_data(e)); - if (key->rsa == NULL) { - return SSH_ERROR; - } - - return SSH_OK; -} - -#ifdef HAVE_GCRYPT_ECC -int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e) -{ - return -1; -} -#endif - -ssh_key pki_key_dup(const ssh_key key, int demote) -{ - ssh_key new; - gcry_sexp_t sexp; - gcry_error_t err; - const char *tmp = NULL; - size_t size; - - ssh_string p = NULL; - ssh_string q = NULL; - ssh_string g = NULL; - ssh_string y = NULL; - ssh_string x = NULL; - - ssh_string e = NULL; - ssh_string n = NULL; - ssh_string d = NULL; - ssh_string u = NULL; - - new = ssh_key_new(); - if (new == NULL) { - return NULL; - } - new->type = key->type; - new->type_c = key->type_c; - if (demote) { - new->flags = SSH_KEY_FLAG_PUBLIC; - } else { - new->flags = key->flags; - } - - switch(key->type) { - case SSH_KEYTYPE_DSS: - sexp = gcry_sexp_find_token(key->dsa, "p", 0); - if (sexp == NULL) { - goto fail; - } - tmp = gcry_sexp_nth_data(sexp, 1, &size); - p = ssh_string_new(size); - if (p == NULL) { - goto fail; - } - ssh_string_fill(p, (char *)tmp, size); - gcry_sexp_release(sexp); - - sexp = gcry_sexp_find_token(key->dsa, "q", 0); - if (sexp == NULL) { - goto fail; - } - tmp = gcry_sexp_nth_data(sexp, 1, &size); - q = ssh_string_new(size); - if (q == NULL) { - goto fail; - } - ssh_string_fill(q, (char *)tmp, size); - gcry_sexp_release(sexp); - - sexp = gcry_sexp_find_token(key->dsa, "g", 0); - if (sexp == NULL) { - goto fail; - } - tmp = gcry_sexp_nth_data(sexp, 1, &size); - g = ssh_string_new(size); - if (g == NULL) { - goto fail; - } - ssh_string_fill(g, (char *)tmp, size); - gcry_sexp_release(sexp); - - sexp = gcry_sexp_find_token(key->dsa, "y", 0); - if (sexp == NULL) { - goto fail; - } - tmp = gcry_sexp_nth_data(sexp, 1, &size); - y = ssh_string_new(size); - if (y == NULL) { - goto fail; - } - ssh_string_fill(y, (char *)tmp, size); - gcry_sexp_release(sexp); - - if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) { - sexp = gcry_sexp_find_token(key->dsa, "x", 0); - if (sexp == NULL) { - goto fail; - } - tmp = gcry_sexp_nth_data(sexp, 1, &size); - x = ssh_string_new(size); - if (x == NULL) { - goto fail; - } - ssh_string_fill(x, (char *)tmp, size); - gcry_sexp_release(sexp); - - err = gcry_sexp_build(&new->dsa, NULL, - "(private-key(dsa(p %b)(q %b)(g %b)(y %b)(x %b)))", - ssh_string_len(p), ssh_string_data(p), - ssh_string_len(q), ssh_string_data(q), - ssh_string_len(g), ssh_string_data(g), - ssh_string_len(y), ssh_string_data(y), - ssh_string_len(x), ssh_string_data(x)); - } else { - err = gcry_sexp_build(&new->dsa, NULL, - "(public-key(dsa(p %b)(q %b)(g %b)(y %b)))", - ssh_string_len(p), ssh_string_data(p), - ssh_string_len(q), ssh_string_data(q), - ssh_string_len(g), ssh_string_data(g), - ssh_string_len(y), ssh_string_data(y)); - } - if (err) { - goto fail; - } - - ssh_string_burn(p); - ssh_string_free(p); - ssh_string_burn(q); - ssh_string_free(q); - ssh_string_burn(g); - ssh_string_free(g); - ssh_string_burn(y); - ssh_string_free(y); - ssh_string_burn(x); - ssh_string_free(x); - break; - case SSH_KEYTYPE_RSA: - case SSH_KEYTYPE_RSA1: - sexp = gcry_sexp_find_token(key->rsa, "e", 0); - if (sexp == NULL) { - goto fail; - } - tmp = gcry_sexp_nth_data(sexp, 1, &size); - e = ssh_string_new(size); - if (e == NULL) { - goto fail; - } - ssh_string_fill(e, (char *)tmp, size); - gcry_sexp_release(sexp); - - sexp = gcry_sexp_find_token(key->rsa, "n", 0); - if (sexp == NULL) { - goto fail; - } - tmp = gcry_sexp_nth_data(sexp, 1, &size); - n = ssh_string_new(size); - if (n == NULL) { - goto fail; - } - ssh_string_fill(n, (char *)tmp, size); - gcry_sexp_release(sexp); - - if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) { - sexp = gcry_sexp_find_token(key->rsa, "d", 0); - if (sexp == NULL) { - goto fail; - } - tmp = gcry_sexp_nth_data(sexp, 1, &size); - d = ssh_string_new(size); - if (e == NULL) { - goto fail; - } - ssh_string_fill(d, (char *)tmp, size); - gcry_sexp_release(sexp); - - sexp = gcry_sexp_find_token(key->rsa, "p", 0); - if (sexp == NULL) { - goto fail; - } - tmp = gcry_sexp_nth_data(sexp, 1, &size); - p = ssh_string_new(size); - if (p == NULL) { - goto fail; - } - ssh_string_fill(p, (char *)tmp, size); - gcry_sexp_release(sexp); - - sexp = gcry_sexp_find_token(key->rsa, "q", 0); - if (sexp == NULL) { - goto fail; - } - tmp = gcry_sexp_nth_data(sexp, 1, &size); - q = ssh_string_new(size); - if (q == NULL) { - goto fail; - } - ssh_string_fill(q, (char *)tmp, size); - gcry_sexp_release(sexp); - - sexp = gcry_sexp_find_token(key->rsa, "u", 0); - if (sexp == NULL) { - goto fail; - } - tmp = gcry_sexp_nth_data(sexp, 1, &size); - u = ssh_string_new(size); - if (u == NULL) { - goto fail; - } - ssh_string_fill(u, (char *)tmp, size); - gcry_sexp_release(sexp); - - err = gcry_sexp_build(&new->rsa, NULL, - "(private-key(rsa(n %b)(e %b)(d %b)(p %b)(q %b)(u %b)))", - ssh_string_len(n), ssh_string_data(n), - ssh_string_len(e), ssh_string_data(e), - ssh_string_len(d), ssh_string_data(d), - ssh_string_len(p), ssh_string_data(p), - ssh_string_len(q), ssh_string_data(q), - ssh_string_len(u), ssh_string_data(u)); - } else { - err = gcry_sexp_build(&new->rsa, NULL, - "(public-key(rsa(n %b)(e %b)))", - ssh_string_len(n), ssh_string_data(n), - ssh_string_len(e), ssh_string_data(e)); - } - - if (err) { - goto fail; - } - - ssh_string_burn(e); - ssh_string_free(e); - ssh_string_burn(n); - ssh_string_free(n); - ssh_string_burn(d); - ssh_string_free(d); - ssh_string_burn(p); - ssh_string_free(p); - ssh_string_burn(q); - ssh_string_free(q); - ssh_string_burn(u); - ssh_string_free(u); - - break; - case SSH_KEYTYPE_ECDSA: - case SSH_KEYTYPE_UNKNOWN: - ssh_key_free(new); - return NULL; - } - - return new; -fail: - gcry_sexp_release(sexp); - ssh_string_burn(p); - ssh_string_free(p); - ssh_string_burn(q); - ssh_string_free(q); - ssh_string_burn(g); - ssh_string_free(g); - ssh_string_burn(y); - ssh_string_free(y); - ssh_string_burn(x); - ssh_string_free(x); - - ssh_string_burn(e); - ssh_string_free(e); - ssh_string_burn(n); - ssh_string_free(n); - ssh_string_burn(u); - ssh_string_free(u); - - ssh_key_free(new); - - return NULL; -} - -static int pki_key_generate(ssh_key key, int parameter, const char *type_s, int type){ - gcry_sexp_t parms; - int rc; - rc = gcry_sexp_build(&parms, - NULL, - "(genkey(%s(nbits %d)(transient-key)))", - type_s, - parameter); - if (rc != 0) - return SSH_ERROR; - if(type == SSH_KEYTYPE_RSA) - rc = gcry_pk_genkey(&key->rsa, parms); - else - rc = gcry_pk_genkey(&key->dsa, parms); - gcry_sexp_release(parms); - if (rc != 0) - return SSH_ERROR; - return SSH_OK; -} - -int pki_key_generate_rsa(ssh_key key, int parameter){ - return pki_key_generate(key, parameter, "rsa", SSH_KEYTYPE_RSA); -} -int pki_key_generate_dss(ssh_key key, int parameter){ - return pki_key_generate(key, parameter, "dsa", SSH_KEYTYPE_DSS); -} - -#ifdef HAVE_GCRYPT_ECC -int pki_key_generate_ecdsa(ssh_key key, int parameter) { - return -1; -} -#endif - -static int _bignum_cmp(const gcry_sexp_t s1, - const gcry_sexp_t s2, - const char *what) -{ - gcry_sexp_t sexp; - bignum b1; - bignum b2; - - sexp = gcry_sexp_find_token(s1, what, 0); - if (sexp == NULL) { - return 1; - } - b1 = gcry_sexp_nth_mpi(sexp, 1, GCRYMPI_FMT_USG); - gcry_sexp_release(sexp); - if (b1 == NULL) { - return 1; - } - - sexp = gcry_sexp_find_token(s2, what, 0); - if (sexp == NULL) { - return 1; - } - b2 = gcry_sexp_nth_mpi(sexp, 1, GCRYMPI_FMT_USG); - gcry_sexp_release(sexp); - if (b2 == NULL) { - return 1; - } - - if (bignum_cmp(b1, b2) != 0) { - return 1; - } - - return 0; -} - -int pki_key_compare(const ssh_key k1, - const ssh_key k2, - enum ssh_keycmp_e what) -{ - switch (k1->type) { - case SSH_KEYTYPE_DSS: - if (_bignum_cmp(k1->dsa, k2->dsa, "p") != 0) { - return 1; - } - - if (_bignum_cmp(k1->dsa, k2->dsa, "q") != 0) { - return 1; - } - - if (_bignum_cmp(k1->dsa, k2->dsa, "g") != 0) { - return 1; - } - - if (_bignum_cmp(k1->dsa, k2->dsa, "y") != 0) { - return 1; - } - - if (what == SSH_KEY_CMP_PRIVATE) { - if (_bignum_cmp(k1->dsa, k2->dsa, "x") != 0) { - return 1; - } - } - break; - case SSH_KEYTYPE_RSA: - case SSH_KEYTYPE_RSA1: - if (_bignum_cmp(k1->rsa, k2->rsa, "e") != 0) { - return 1; - } - - if (_bignum_cmp(k1->rsa, k2->rsa, "n") != 0) { - return 1; - } - - if (what == SSH_KEY_CMP_PRIVATE) { - if (_bignum_cmp(k1->rsa, k2->rsa, "d") != 0) { - return 1; - } - - if (_bignum_cmp(k1->rsa, k2->rsa, "p") != 0) { - return 1; - } - - if (_bignum_cmp(k1->rsa, k2->rsa, "q") != 0) { - return 1; - } - - if (_bignum_cmp(k1->rsa, k2->rsa, "u") != 0) { - return 1; - } - } - break; - case SSH_KEYTYPE_ECDSA: - case SSH_KEYTYPE_UNKNOWN: - return 1; - } - - return 0; -} - -ssh_string pki_publickey_to_blob(const ssh_key key) -{ - ssh_buffer buffer; - ssh_string type_s; - ssh_string str = NULL; - ssh_string e = NULL; - ssh_string n = NULL; - ssh_string p = NULL; - ssh_string g = NULL; - ssh_string q = NULL; - const char *tmp = NULL; - size_t size; - gcry_sexp_t sexp; - int rc; - - buffer = ssh_buffer_new(); - if (buffer == NULL) { - return NULL; - } - - type_s = ssh_string_from_char(key->type_c); - if (type_s == NULL) { - ssh_buffer_free(buffer); - return NULL; - } - - rc = buffer_add_ssh_string(buffer, type_s); - ssh_string_free(type_s); - if (rc < 0) { - ssh_buffer_free(buffer); - return NULL; - } - - switch (key->type) { - case SSH_KEYTYPE_DSS: - sexp = gcry_sexp_find_token(key->dsa, "p", 0); - if (sexp == NULL) { - goto fail; - } - tmp = gcry_sexp_nth_data(sexp, 1, &size); - p = ssh_string_new(size); - if (p == NULL) { - goto fail; - } - ssh_string_fill(p, (char *) tmp, size); - gcry_sexp_release(sexp); - - sexp = gcry_sexp_find_token(key->dsa, "q", 0); - if (sexp == NULL) { - goto fail; |