/** @internal * @brief Starts diffie-hellman-group1 key exchange */ int ssh_client_dh_init(ssh_session session){ ssh_string e = NULL; int rc; if (dh_generate_x(session) < 0) { goto error; } if (dh_generate_e(session) < 0) { goto error; } e = dh_get_e(session); if (e == NULL) { goto error; } rc = ssh_buffer_pack(session->out_buffer, "bS", SSH2_MSG_KEXDH_INIT, e); if (rc != SSH_OK) { goto error; } ssh_string_burn(e); ssh_string_free(e); e=NULL; rc = packet_send(session); return rc; error: if(e != NULL){ ssh_string_burn(e); ssh_string_free(e); } return SSH_ERROR; }
int ssh_client_dh_reply(ssh_session session, ssh_buffer packet){ ssh_string f; ssh_string pubkey = NULL; ssh_string signature = NULL; int rc; pubkey = buffer_get_ssh_string(packet); if (pubkey == NULL){ ssh_set_error(session,SSH_FATAL, "No public key in packet"); goto error; } dh_import_pubkey(session, pubkey); f = buffer_get_ssh_string(packet); if (f == NULL) { ssh_set_error(session,SSH_FATAL, "No F number in packet"); goto error; } rc = dh_import_f(session, f); ssh_string_burn(f); ssh_string_free(f); if (rc < 0) { ssh_set_error(session, SSH_FATAL, "Cannot import f number"); goto error; } signature = buffer_get_ssh_string(packet); if (signature == NULL) { ssh_set_error(session, SSH_FATAL, "No signature in packet"); goto error; } session->next_crypto->dh_server_signature = signature; signature=NULL; /* ownership changed */ if (dh_build_k(session) < 0) { ssh_set_error(session, SSH_FATAL, "Cannot build k number"); goto error; } /* Send the MSG_NEWKEYS */ if (buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) { goto error; } rc=packet_send(session); SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); return rc; error: return SSH_ERROR; }
/* * Extract an MPI from the given s-expression SEXP named NAME which is * encoded using INFORMAT and store it in a newly allocated ssh_string * encoded using OUTFORMAT. */ ssh_string ssh_sexp_extract_mpi(const gcry_sexp_t sexp, const char *name, enum gcry_mpi_format informat, enum gcry_mpi_format outformat) { gpg_error_t err; ssh_string result = NULL; gcry_sexp_t fragment = NULL; gcry_mpi_t mpi = NULL; size_t size; fragment = gcry_sexp_find_token(sexp, name, 0); if (fragment == NULL) { goto fail; } mpi = gcry_sexp_nth_mpi(fragment, 1, informat); if (mpi == NULL) { goto fail; } err = gcry_mpi_print(outformat, NULL, 0, &size, mpi); if (err != 0) { goto fail; } result = ssh_string_new(size); if (result == NULL) { goto fail; } err = gcry_mpi_print(outformat, ssh_string_data(result), size, NULL, mpi); if (err != 0) { ssh_string_burn(result); ssh_string_free(result); result = NULL; goto fail; } fail: gcry_sexp_release(fragment); gcry_mpi_release(mpi); return result; }
ssh_public_key publickey_make_dss(ssh_session session, ssh_buffer buffer) { ssh_string p = NULL; ssh_string q = NULL; ssh_string g = NULL; ssh_string pubkey = NULL; ssh_public_key key = NULL; key = malloc(sizeof(struct ssh_public_key_struct)); if (key == NULL) { ssh_buffer_free(buffer); return NULL; } ZERO_STRUCTP(key); key->type = SSH_KEYTYPE_DSS; key->type_c = ssh_type_to_char(key->type); p = buffer_get_ssh_string(buffer); q = buffer_get_ssh_string(buffer); g = buffer_get_ssh_string(buffer); pubkey = buffer_get_ssh_string(buffer); ssh_buffer_free(buffer); /* we don't need it anymore */ if (p == NULL || q == NULL || g == NULL || pubkey == NULL) { ssh_set_error(session, SSH_FATAL, "Invalid DSA public key"); goto error; } #ifdef HAVE_LIBGCRYPT gcry_sexp_build(&key->dsa_pub, 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_pub == NULL) { goto error; } #elif defined HAVE_LIBCRYPTO key->dsa_pub = DSA_new(); if (key->dsa_pub == NULL) { goto error; } key->dsa_pub->p = make_string_bn(p); key->dsa_pub->q = make_string_bn(q); key->dsa_pub->g = make_string_bn(g); key->dsa_pub->pub_key = make_string_bn(pubkey); if (key->dsa_pub->p == NULL || key->dsa_pub->q == NULL || key->dsa_pub->g == NULL || key->dsa_pub->pub_key == NULL) { goto error; } #endif /* HAVE_LIBCRYPTO */ #ifdef DEBUG_CRYPTO ssh_print_hexa("p", ssh_string_data(p), ssh_string_len(p)); ssh_print_hexa("q", ssh_string_data(q), ssh_string_len(q)); ssh_print_hexa("g", ssh_string_data(g), ssh_string_len(g)); #endif 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(pubkey); ssh_string_free(pubkey); return key; error: 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(pubkey); ssh_string_free(pubkey); publickey_free(key); return NULL; }
static int rsa_public_to_string(gcry_sexp_t key, ssh_buffer buffer) { #elif defined HAVE_LIBCRYPTO static int rsa_public_to_string(RSA *key, ssh_buffer buffer) { #endif ssh_string e = NULL; ssh_string n = NULL; int rc = -1; #ifdef HAVE_LIBGCRYPT const char *tmp; size_t size; gcry_sexp_t sexp; sexp = gcry_sexp_find_token(key, "n", 0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp, 1, &size); n = ssh_string_new(size); if (n == NULL) { goto error; } ssh_string_fill(n, (char *) tmp, size); gcry_sexp_release(sexp); sexp = gcry_sexp_find_token(key, "e", 0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp, 1, &size); e = ssh_string_new(size); if (e == NULL) { goto error; } ssh_string_fill(e, (char *) tmp, size); #elif defined HAVE_LIBCRYPTO e = make_bignum_string(key->e); n = make_bignum_string(key->n); if (e == NULL || n == NULL) { goto error; } #endif if (buffer_add_ssh_string(buffer, e) < 0) { goto error; } if (buffer_add_ssh_string(buffer, n) < 0) { goto error; } rc = 0; error: #ifdef HAVE_LIBGCRYPT gcry_sexp_release(sexp); #endif ssh_string_burn(e); ssh_string_free(e); ssh_string_burn(n); ssh_string_free(n); return rc; #if defined(HAVE_LIBGCRYPT) || defined(HAVE_LIBCRYPTO) }
static int dsa_public_to_string(gcry_sexp_t key, ssh_buffer buffer) { #elif defined HAVE_LIBCRYPTO static int dsa_public_to_string(DSA *key, ssh_buffer buffer) { #endif ssh_string p = NULL; ssh_string q = NULL; ssh_string g = NULL; ssh_string n = NULL; int rc = -1; #ifdef HAVE_LIBGCRYPT const char *tmp = NULL; size_t size; gcry_sexp_t sexp; sexp = gcry_sexp_find_token(key, "p", 0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp, 1, &size); p = ssh_string_new(size); if (p == NULL) { goto error; } ssh_string_fill(p, (char *) tmp, size); gcry_sexp_release(sexp); sexp = gcry_sexp_find_token(key, "q", 0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp, 1, &size); q = ssh_string_new(size); if (q == NULL) { goto error; } ssh_string_fill(q, (char *) tmp, size); gcry_sexp_release(sexp); sexp = gcry_sexp_find_token(key, "g", 0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp, 1, &size); g = ssh_string_new(size); if (g == NULL) { goto error; } ssh_string_fill(g, (char *) tmp, size); gcry_sexp_release(sexp); sexp = gcry_sexp_find_token(key, "y", 0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp, 1, &size); n = ssh_string_new(size); if (n == NULL) { goto error; } ssh_string_fill(n, (char *) tmp, size); #elif defined HAVE_LIBCRYPTO p = make_bignum_string(key->p); q = make_bignum_string(key->q); g = make_bignum_string(key->g); n = make_bignum_string(key->pub_key); if (p == NULL || q == NULL || g == NULL || n == NULL) { goto error; } #endif /* HAVE_LIBCRYPTO */ if (buffer_add_ssh_string(buffer, p) < 0) { goto error; } if (buffer_add_ssh_string(buffer, q) < 0) { goto error; } if (buffer_add_ssh_string(buffer, g) < 0) { goto error; } if (buffer_add_ssh_string(buffer, n) < 0) { goto error; } rc = 0; error: #ifdef HAVE_LIBGCRYPT gcry_sexp_release(sexp); #endif 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(n); ssh_string_free(n); return rc; #if defined(HAVE_LIBGCRYPT) || defined(HAVE_LIBCRYPTO) }
/** * @brief Make a public_key object out of a private_key object. * * @param[in] prv The private key to generate the public key. * * @returns The generated public key, NULL on error. * * @see publickey_to_string() */ ssh_public_key publickey_from_privatekey(ssh_private_key prv) { ssh_public_key key = NULL; #ifdef HAVE_LIBGCRYPT gcry_sexp_t sexp; 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 e = NULL; ssh_string n = NULL; #endif /* HAVE_LIBGCRYPT */ key = malloc(sizeof(struct ssh_public_key_struct)); if (key == NULL) { return NULL; } ZERO_STRUCTP(key); key->type = prv->type; switch(key->type) { case SSH_KEYTYPE_DSS: #ifdef HAVE_LIBGCRYPT sexp = gcry_sexp_find_token(prv->dsa_priv, "p", 0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp, 1, &size); p = ssh_string_new(size); if (p == NULL) { goto error; } ssh_string_fill(p,(char *) tmp, size); gcry_sexp_release(sexp); sexp = gcry_sexp_find_token(prv->dsa_priv,"q",0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp,1,&size); q = ssh_string_new(size); if (q == NULL) { goto error; } ssh_string_fill(q,(char *) tmp,size); gcry_sexp_release(sexp); sexp = gcry_sexp_find_token(prv->dsa_priv, "g", 0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp,1,&size); g = ssh_string_new(size); if (g == NULL) { goto error; } ssh_string_fill(g,(char *) tmp,size); gcry_sexp_release(sexp); sexp = gcry_sexp_find_token(prv->dsa_priv,"y",0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp,1,&size); y = ssh_string_new(size); if (y == NULL) { goto error; } ssh_string_fill(y,(char *) tmp,size); gcry_sexp_release(sexp); gcry_sexp_build(&key->dsa_pub, 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)); 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); #elif defined HAVE_LIBCRYPTO key->dsa_pub = DSA_new(); if (key->dsa_pub == NULL) { goto error; } key->dsa_pub->p = BN_dup(prv->dsa_priv->p); key->dsa_pub->q = BN_dup(prv->dsa_priv->q); key->dsa_pub->g = BN_dup(prv->dsa_priv->g); key->dsa_pub->pub_key = BN_dup(prv->dsa_priv->pub_key); if (key->dsa_pub->p == NULL || key->dsa_pub->q == NULL || key->dsa_pub->g == NULL || key->dsa_pub->pub_key == NULL) { goto error; } #endif /* HAVE_LIBCRYPTO */ break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: #ifdef HAVE_LIBGCRYPT sexp = gcry_sexp_find_token(prv->rsa_priv, "n", 0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp, 1, &size); n = ssh_string_new(size); if (n == NULL) { goto error; } ssh_string_fill(n, (char *) tmp, size); gcry_sexp_release(sexp); sexp = gcry_sexp_find_token(prv->rsa_priv, "e", 0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp, 1, &size); e = ssh_string_new(size); if (e == NULL) { goto error; } ssh_string_fill(e, (char *) tmp, size); gcry_sexp_release(sexp); gcry_sexp_build(&key->rsa_pub, 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_pub == NULL) { goto error; } ssh_string_burn(e); ssh_string_free(e); ssh_string_burn(n); ssh_string_free(n); #elif defined HAVE_LIBCRYPTO key->rsa_pub = RSA_new(); if (key->rsa_pub == NULL) { goto error; } key->rsa_pub->e = BN_dup(prv->rsa_priv->e); key->rsa_pub->n = BN_dup(prv->rsa_priv->n); if (key->rsa_pub->e == NULL || key->rsa_pub->n == NULL) { goto error; } #endif break; default: publickey_free(key); return NULL; } key->type_c = ssh_type_to_char(prv->type); return key; error: #ifdef HAVE_LIBGCRYPT 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(e); ssh_string_free(e); ssh_string_burn(n); ssh_string_free(n); #endif publickey_free(key); return NULL; }
ssh_public_key publickey_make_rsa(ssh_session session, ssh_buffer buffer, int type) { ssh_string e = NULL; ssh_string n = NULL; ssh_public_key key = NULL; key = malloc(sizeof(struct ssh_public_key_struct)); if (key == NULL) { ssh_buffer_free(buffer); return NULL; } ZERO_STRUCTP(key); key->type = type; key->type_c = ssh_type_to_char(key->type); e = buffer_get_ssh_string(buffer); n = buffer_get_ssh_string(buffer); ssh_buffer_free(buffer); /* we don't need it anymore */ if(e == NULL || n == NULL) { ssh_set_error(session, SSH_FATAL, "Invalid RSA public key"); goto error; } #ifdef HAVE_LIBGCRYPT gcry_sexp_build(&key->rsa_pub, 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_pub == NULL) { goto error; } #elif HAVE_LIBCRYPTO key->rsa_pub = RSA_new(); if (key->rsa_pub == NULL) { goto error; } key->rsa_pub->e = make_string_bn(e); key->rsa_pub->n = make_string_bn(n); if (key->rsa_pub->e == NULL || key->rsa_pub->n == NULL) { goto error; } #endif #ifdef DEBUG_CRYPTO ssh_print_hexa("e", ssh_string_data(e), ssh_string_len(e)); ssh_print_hexa("n", ssh_string_data(n), ssh_string_len(n)); #endif ssh_string_burn(e); ssh_string_free(e); ssh_string_burn(n); ssh_string_free(n); return key; error: ssh_string_burn(e); ssh_string_free(e); ssh_string_burn(n); ssh_string_free(n); publickey_free(key); return NULL; }
static int pki_import_pubkey_buffer(ssh_buffer buffer, enum ssh_keytypes_e type, ssh_key *pkey) { ssh_key key; int rc; key = ssh_key_new(); if (key == NULL) { return SSH_ERROR; } key->type = type; key->type_c = ssh_key_type_to_char(type); key->flags = SSH_KEY_FLAG_PUBLIC; switch (type) { case SSH_KEYTYPE_DSS: { ssh_string p; ssh_string q; ssh_string g; ssh_string pubkey; p = ssh_buffer_get_ssh_string(buffer); if (p == NULL) { goto fail; } q = ssh_buffer_get_ssh_string(buffer); if (q == NULL) { ssh_string_burn(p); ssh_string_free(p); goto fail; } g = ssh_buffer_get_ssh_string(buffer); if (g == NULL) { ssh_string_burn(p); ssh_string_free(p); ssh_string_burn(q); ssh_string_free(q); goto fail; } pubkey = ssh_buffer_get_ssh_string(buffer); if (pubkey == NULL) { ssh_string_burn(p); ssh_string_free(p); ssh_string_burn(q); ssh_string_free(q); ssh_string_burn(g); ssh_string_free(g); goto fail; } rc = pki_pubkey_build_dss(key, p, q, g, pubkey); #ifdef DEBUG_CRYPTO ssh_print_hexa("p", ssh_string_data(p), ssh_string_len(p)); ssh_print_hexa("q", ssh_string_data(q), ssh_string_len(q)); ssh_print_hexa("g", ssh_string_data(g), ssh_string_len(g)); #endif 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(pubkey); ssh_string_free(pubkey); if (rc == SSH_ERROR) { goto fail; } } break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: { ssh_string e; ssh_string n; e = ssh_buffer_get_ssh_string(buffer); if (e == NULL) { goto fail; } n = ssh_buffer_get_ssh_string(buffer); if (n == NULL) { ssh_string_burn(e); ssh_string_free(e); goto fail; } rc = pki_pubkey_build_rsa(key, e, n); #ifdef DEBUG_CRYPTO ssh_print_hexa("e", ssh_string_data(e), ssh_string_len(e)); ssh_print_hexa("n", ssh_string_data(n), ssh_string_len(n)); #endif ssh_string_burn(e); ssh_string_free(e); ssh_string_burn(n); ssh_string_free(n); if (rc == SSH_ERROR) { goto fail; } } break; case SSH_KEYTYPE_ECDSA: #ifdef HAVE_ECC { ssh_string e; ssh_string i; int nid; i = ssh_buffer_get_ssh_string(buffer); if (i == NULL) { goto fail; } nid = pki_key_ecdsa_nid_from_name(ssh_string_get_char(i)); ssh_string_free(i); if (nid == -1) { goto fail; } e = ssh_buffer_get_ssh_string(buffer); if (e == NULL) { goto fail; } rc = pki_pubkey_build_ecdsa(key, nid, e); ssh_string_burn(e); ssh_string_free(e); if (rc < 0) { goto fail; } /* Update key type */ key->type_c = ssh_pki_key_ecdsa_name(key); } break; #endif case SSH_KEYTYPE_ED25519: { ssh_string pubkey = ssh_buffer_get_ssh_string(buffer); if (ssh_string_len(pubkey) != ED25519_PK_LEN) { SSH_LOG(SSH_LOG_WARN, "Invalid public key length"); ssh_string_burn(pubkey); ssh_string_free(pubkey); goto fail; } key->ed25519_pubkey = malloc(ED25519_PK_LEN); if (key->ed25519_pubkey == NULL) { ssh_string_burn(pubkey); ssh_string_free(pubkey); goto fail; } memcpy(key->ed25519_pubkey, ssh_string_data(pubkey), ED25519_PK_LEN); ssh_string_burn(pubkey); ssh_string_free(pubkey); } break; case SSH_KEYTYPE_DSS_CERT01: case SSH_KEYTYPE_RSA_CERT01: case SSH_KEYTYPE_UNKNOWN: default: SSH_LOG(SSH_LOG_WARN, "Unknown public key protocol %d", type); goto fail; } *pkey = key; return SSH_OK; fail: ssh_key_free(key); return SSH_ERROR; }
int ssh_userauth1_password(ssh_session session, const char *username, const char *password) { ssh_string pwd = NULL; int rc; enter_function(); rc = send_username(session, username); if (rc != SSH_AUTH_DENIED) { leave_function(); return rc; } /* we trick a bit here. A known flaw in SSH1 protocol is that it's * easy to guess password sizes. * not that sure ... */ /* XXX fix me here ! */ /* cisco IOS doesn't like when a password is followed by zeroes and random pad. */ if(1 || strlen(password) >= 128) { /* not risky to disclose the size of such a big password .. */ pwd = ssh_string_from_char(password); if (pwd == NULL) { leave_function(); return SSH_AUTH_ERROR; } } else { /* fill the password string from random things. the strcpy * ensure there is at least a nul byte after the password. * most implementation won't see the garbage at end. * why garbage ? because nul bytes will be compressed by * gzip and disclose password len. */ pwd = ssh_string_new(128); if (pwd == NULL) { leave_function(); return SSH_AUTH_ERROR; } ssh_get_random( pwd->string, 128, 0); strcpy((char *) pwd->string, password); } if (buffer_add_u8(session->out_buffer, SSH_CMSG_AUTH_PASSWORD) < 0) { ssh_string_burn(pwd); ssh_string_free(pwd); leave_function(); return SSH_AUTH_ERROR; } if (buffer_add_ssh_string(session->out_buffer, pwd) < 0) { ssh_string_burn(pwd); ssh_string_free(pwd); leave_function(); return SSH_AUTH_ERROR; } ssh_string_burn(pwd); ssh_string_free(pwd); session->auth_state=SSH_AUTH_STATE_NONE; if (packet_send(session) == SSH_ERROR) { leave_function(); return SSH_AUTH_ERROR; } rc = wait_auth1_status(session); leave_function(); return rc; }
/** @internal * @brief launches the DH handshake state machine * @param session session handle * @returns SSH_OK or SSH_ERROR * @warning this function returning is no proof that DH handshake is * completed */ static int dh_handshake(ssh_session session) { ssh_string e = NULL; ssh_string f = NULL; ssh_string signature = NULL; int rc = SSH_ERROR; enter_function(); switch (session->dh_handshake_state) { case DH_STATE_INIT: if (buffer_add_u8(session->out_buffer, SSH2_MSG_KEXDH_INIT) < 0) { goto error; } if (dh_generate_x(session) < 0) { goto error; } if (dh_generate_e(session) < 0) { goto error; } e = dh_get_e(session); if (e == NULL) { goto error; } if (buffer_add_ssh_string(session->out_buffer, e) < 0) { goto error; } ssh_string_burn(e); ssh_string_free(e); e=NULL; rc = packet_send(session); if (rc == SSH_ERROR) { goto error; } session->dh_handshake_state = DH_STATE_INIT_SENT; case DH_STATE_INIT_SENT: /* wait until ssh_packet_dh_reply is called */ break; case DH_STATE_NEWKEYS_SENT: /* wait until ssh_packet_newkeys is called */ break; case DH_STATE_FINISHED: leave_function(); return SSH_OK; default: ssh_set_error(session, SSH_FATAL, "Invalid state in dh_handshake(): %d", session->dh_handshake_state); leave_function(); return SSH_ERROR; } leave_function(); return SSH_AGAIN; error: if(e != NULL){ ssh_string_burn(e); ssh_string_free(e); } if(f != NULL){ ssh_string_burn(f); ssh_string_free(f); } if(signature != NULL){ ssh_string_burn(signature); ssh_string_free(signature); } leave_function(); return rc; }
int ssh_pki_import_pubkey_base64(ssh_session session, const char *b64_key, enum ssh_keytypes_e type, ssh_key *pkey) { ssh_buffer buffer; ssh_key key; int rc; key = ssh_key_new(); if (key == NULL) { return SSH_ERROR; } key->type = type; key->type_c = ssh_key_type_to_char(type); key->flags = SSH_KEY_FLAG_PUBLIC; buffer = base64_to_bin(b64_key); switch (type) { case SSH_KEYTYPE_DSS: { ssh_string p; ssh_string q; ssh_string g; ssh_string pubkey; p = buffer_get_ssh_string(buffer); if (p == NULL) { goto fail; } q = buffer_get_ssh_string(buffer); if (q == NULL) { ssh_string_burn(p); ssh_string_free(p); goto fail; } g = buffer_get_ssh_string(buffer); if (g == NULL) { ssh_string_burn(p); ssh_string_free(p); ssh_string_burn(q); ssh_string_free(q); goto fail; } pubkey = buffer_get_ssh_string(buffer); if (g == NULL) { ssh_string_burn(p); ssh_string_free(p); ssh_string_burn(q); ssh_string_free(q); ssh_string_burn(g); ssh_string_free(g); goto fail; } rc = pki_pubkey_build_dss(key, p, q, g, pubkey); #ifdef DEBUG_CRYPTO ssh_print_hexa("p", ssh_string_data(p), ssh_string_len(p)); ssh_print_hexa("q", ssh_string_data(q), ssh_string_len(q)); ssh_print_hexa("g", ssh_string_data(g), ssh_string_len(g)); #endif ssh_string_burn(p); ssh_string_free(p); ssh_string_burn(q); ssh_string_free(q); ssh_string_burn(g); ssh_string_free(g); if (rc == SSH_ERROR) { goto fail; } } break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: { ssh_string e; ssh_string n; e = buffer_get_ssh_string(buffer); if (e == NULL) { goto fail; } n = buffer_get_ssh_string(buffer); if (n == NULL) { ssh_string_burn(e); ssh_string_free(e); goto fail; } rc = pki_pubkey_build_rsa(key, e, n); #ifdef DEBUG_CRYPTO ssh_print_hexa("e", ssh_string_data(e), ssh_string_len(e)); ssh_print_hexa("n", ssh_string_data(n), ssh_string_len(n)); #endif ssh_string_burn(e); ssh_string_free(e); ssh_string_burn(n); ssh_string_free(n); if (rc == SSH_ERROR) { goto fail; } } break; case SSH_KEYTYPE_ECDSA: case SSH_KEYTYPE_UNKNOWN: ssh_set_error(session, SSH_FATAL, "Unknown public key protocol %d", type); goto fail; } ssh_buffer_free(buffer); *pkey = key; return SSH_OK; fail: ssh_buffer_free(buffer); ssh_key_free(key); return SSH_ERROR; }
void string_burn(ssh_string str){ ssh_string_burn(str); }
int ssh_generate_session_keys(ssh_session session) { ssh_string k_string = NULL; struct ssh_crypto_struct *crypto = session->next_crypto; unsigned char *key = NULL; unsigned char *IV_cli_to_srv = NULL; unsigned char *IV_srv_to_cli = NULL; unsigned char *enckey_cli_to_srv = NULL; unsigned char *enckey_srv_to_cli = NULL; unsigned char *intkey_cli_to_srv = NULL; unsigned char *intkey_srv_to_cli = NULL; size_t key_len = 0; size_t IV_len = 0; size_t enckey_cli_to_srv_len = 0; size_t enckey_srv_to_cli_len = 0; size_t intkey_cli_to_srv_len = 0; size_t intkey_srv_to_cli_len = 0; int rc = -1; k_string = ssh_make_bignum_string(crypto->shared_secret); if (k_string == NULL) { ssh_set_error_oom(session); goto error; } /* See RFC4251 Section 5 for the definition of mpint which is the * encoding we need to use for key in the SSH KDF */ key = (unsigned char *)k_string; key_len = ssh_string_len(k_string) + 4; IV_len = crypto->digest_len; if (session->client) { enckey_cli_to_srv_len = crypto->out_cipher->keysize / 8; enckey_srv_to_cli_len = crypto->in_cipher->keysize / 8; intkey_cli_to_srv_len = hmac_digest_len(crypto->out_hmac); intkey_srv_to_cli_len = hmac_digest_len(crypto->in_hmac); } else { enckey_cli_to_srv_len = crypto->in_cipher->keysize / 8; enckey_srv_to_cli_len = crypto->out_cipher->keysize / 8; intkey_cli_to_srv_len = hmac_digest_len(crypto->in_hmac); intkey_srv_to_cli_len = hmac_digest_len(crypto->out_hmac); } IV_cli_to_srv = malloc(IV_len); IV_srv_to_cli = malloc(IV_len); enckey_cli_to_srv = malloc(enckey_cli_to_srv_len); enckey_srv_to_cli = malloc(enckey_srv_to_cli_len); intkey_cli_to_srv = malloc(intkey_cli_to_srv_len); intkey_srv_to_cli = malloc(intkey_srv_to_cli_len); if (IV_cli_to_srv == NULL || IV_srv_to_cli == NULL || enckey_cli_to_srv == NULL || enckey_srv_to_cli == NULL || intkey_cli_to_srv == NULL || intkey_srv_to_cli == NULL) { ssh_set_error_oom(session); goto error; } /* IV */ rc = ssh_kdf(crypto, key, key_len, 'A', IV_cli_to_srv, IV_len); if (rc < 0) { goto error; } rc = ssh_kdf(crypto, key, key_len, 'B', IV_srv_to_cli, IV_len); if (rc < 0) { goto error; } /* Encryption Key */ rc = ssh_kdf(crypto, key, key_len, 'C', enckey_cli_to_srv, enckey_cli_to_srv_len); if (rc < 0) { goto error; } rc = ssh_kdf(crypto, key, key_len, 'D', enckey_srv_to_cli, enckey_srv_to_cli_len); if (rc < 0) { goto error; } /* Integrity Key */ rc = ssh_kdf(crypto, key, key_len, 'E', intkey_cli_to_srv, intkey_cli_to_srv_len); if (rc < 0) { goto error; } rc = ssh_kdf(crypto, key, key_len, 'F', intkey_srv_to_cli, intkey_srv_to_cli_len); if (rc < 0) { goto error; } if (session->client) { crypto->encryptIV = IV_cli_to_srv; crypto->decryptIV = IV_srv_to_cli; crypto->encryptkey = enckey_cli_to_srv; crypto->decryptkey = enckey_srv_to_cli; crypto->encryptMAC = intkey_cli_to_srv; crypto->decryptMAC = intkey_srv_to_cli; } else { crypto->encryptIV = IV_srv_to_cli; crypto->decryptIV = IV_cli_to_srv; crypto->encryptkey = enckey_srv_to_cli; crypto->decryptkey = enckey_cli_to_srv; crypto->encryptMAC = intkey_srv_to_cli; crypto->decryptMAC = intkey_cli_to_srv; } #ifdef DEBUG_CRYPTO ssh_print_hexa("Client to Server IV", IV_cli_to_srv, IV_len); ssh_print_hexa("Server to Client IV", IV_srv_to_cli, IV_len); ssh_print_hexa("Client to Server Encryption Key", enckey_cli_to_srv, enckey_cli_to_srv_len); ssh_print_hexa("Server to Client Encryption Key", enckey_srv_to_cli, enckey_srv_to_cli_len); ssh_print_hexa("Client to Server Integrity Key", intkey_cli_to_srv, intkey_cli_to_srv_len); ssh_print_hexa("Server to Client Integrity Key", intkey_srv_to_cli, intkey_srv_to_cli_len); #endif rc = 0; error: ssh_string_burn(k_string); ssh_string_free(k_string); if (rc != 0) { free(IV_cli_to_srv); free(IV_srv_to_cli); free(enckey_cli_to_srv); free(enckey_srv_to_cli); free(intkey_cli_to_srv); free(intkey_srv_to_cli); } return rc; }