/* * Processes input from the client and the program. Input data is stored * in buffers and processed later. */ static void process_input(struct ssh *ssh, fd_set *readset) { int len, r; char buf[16384]; /* Read and buffer any input data from the client. */ if (FD_ISSET(connection_in, readset)) { len = read(connection_in, buf, sizeof(buf)); if (len == 0) { verbose("Connection closed by %.100s", ssh_remote_ipaddr(ssh)); connection_closed = 1; if (compat20) return; cleanup_exit(255); } else if (len < 0) { if (errno != EINTR && errno != EAGAIN) { verbose("Read error from remote host " "%.100s: %.100s", ssh_remote_ipaddr(ssh), strerror(errno)); cleanup_exit(255); } } else { /* Buffer any received data. */ ssh_packet_process_incoming(ssh, buf, len); } } if (compat20) return; /* Read and buffer any available stdout data from the program. */ if (!fdout_eof && FD_ISSET(fdout, readset)) { len = read(fdout, buf, sizeof(buf)); if (len < 0 && (errno == EINTR || errno == EAGAIN)) { /* do nothing */ } else if (len <= 0) { fdout_eof = 1; } else { if ((r = sshbuf_put(stdout_buffer, buf, len)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); fdout_bytes += len; } } /* Read and buffer any available stderr data from the program. */ if (!fderr_eof && FD_ISSET(fderr, readset)) { len = read(fderr, buf, sizeof(buf)); if (len < 0 && (errno == EINTR || errno == EAGAIN)) { /* do nothing */ } else if (len <= 0) { fderr_eof = 1; } else { if ((r = sshbuf_put(stderr_buffer, buf, len)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); } } }
int kexgex_hash( int hash_alg, const char *client_version_string, const char *server_version_string, const u_char *ckexinit, size_t ckexinitlen, const u_char *skexinit, size_t skexinitlen, const u_char *serverhostkeyblob, size_t sbloblen, int min, int wantbits, int max, const BIGNUM *prime, const BIGNUM *gen, const BIGNUM *client_dh_pub, const BIGNUM *server_dh_pub, const BIGNUM *shared_secret, u_char **hash, size_t *hashlen) { struct sshbuf *b; static u_char digest[SSH_DIGEST_MAX_LENGTH]; int r; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 || (r = sshbuf_put_cstring(b, server_version_string)) != 0 || /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 || (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 || (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 || (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 || (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 || (min != -1 && (r = sshbuf_put_u32(b, min)) != 0) || (r = sshbuf_put_u32(b, wantbits)) != 0 || (max != -1 && (r = sshbuf_put_u32(b, max)) != 0) || (r = sshbuf_put_bignum2(b, prime)) != 0 || (r = sshbuf_put_bignum2(b, gen)) != 0 || (r = sshbuf_put_bignum2(b, client_dh_pub)) != 0 || (r = sshbuf_put_bignum2(b, server_dh_pub)) != 0 || (r = sshbuf_put_bignum2(b, shared_secret)) != 0) { sshbuf_free(b); return r; } #ifdef DEBUG_KEXDH sshbuf_dump(b, stderr); #endif if (ssh_digest_buffer(hash_alg, b, digest, sizeof(digest)) != 0) { sshbuf_free(b); return SSH_ERR_LIBCRYPTO_ERROR; } sshbuf_free(b); *hash = digest; *hashlen = ssh_digest_bytes(hash_alg); #ifdef DEBUG_KEXDH dump_digest("hash", digest, *hashlen); #endif return 0; }
int kex_ecdh_hash( const EVP_MD *evp_md, const EC_GROUP *ec_group, const char *client_version_string, const char *server_version_string, const u_char *ckexinit, size_t ckexinitlen, const u_char *skexinit, size_t skexinitlen, const u_char *serverhostkeyblob, size_t sbloblen, const EC_POINT *client_dh_pub, const EC_POINT *server_dh_pub, const BIGNUM *shared_secret, u_char **hash, size_t *hashlen) { struct sshbuf *b; EVP_MD_CTX md; static u_char digest[EVP_MAX_MD_SIZE]; int r; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 || (r = sshbuf_put_cstring(b, server_version_string)) != 0 || /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 || (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 || (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 || (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 || (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 || (r = sshbuf_put_ec(b, client_dh_pub, ec_group)) != 0 || (r = sshbuf_put_ec(b, server_dh_pub, ec_group)) != 0 || (r = sshbuf_put_bignum2(b, shared_secret)) != 0) { sshbuf_free(b); return r; } #ifdef DEBUG_KEX sshbuf_dump(b, stderr); #endif if (EVP_DigestInit(&md, evp_md) != 1 || EVP_DigestUpdate(&md, sshbuf_ptr(b), sshbuf_len(b)) != 1 || EVP_DigestFinal(&md, digest, NULL) != 1) { sshbuf_free(b); return SSH_ERR_LIBCRYPTO_ERROR; } sshbuf_free(b); #ifdef DEBUG_KEX dump_digest("hash", digest, EVP_MD_size(evp_md)); #endif *hash = digest; *hashlen = EVP_MD_size(evp_md); return 0; }
int kex_ecdh_hash( int hash_alg, const EC_GROUP *ec_group, const char *client_version_string, const char *server_version_string, const u_char *ckexinit, size_t ckexinitlen, const u_char *skexinit, size_t skexinitlen, const u_char *serverhostkeyblob, size_t sbloblen, const EC_POINT *client_dh_pub, const EC_POINT *server_dh_pub, const BIGNUM *shared_secret, u_char *hash, size_t *hashlen) { struct sshbuf *b; int r; if (*hashlen < ssh_digest_bytes(hash_alg)) return SSH_ERR_INVALID_ARGUMENT; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 || (r = sshbuf_put_cstring(b, server_version_string)) != 0 || /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 || (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 || (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 || (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 || (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 || (r = sshbuf_put_ec(b, client_dh_pub, ec_group)) != 0 || (r = sshbuf_put_ec(b, server_dh_pub, ec_group)) != 0 || (r = sshbuf_put_bignum2(b, shared_secret)) != 0) { sshbuf_free(b); return r; } #ifdef DEBUG_KEX sshbuf_dump(b, stderr); #endif if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) { sshbuf_free(b); return SSH_ERR_LIBCRYPTO_ERROR; } sshbuf_free(b); *hashlen = ssh_digest_bytes(hash_alg); #ifdef DEBUG_KEX dump_digest("hash", hash, *hashlen); #endif return 0; }
char * ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *major_status, OM_uint32 *minor_status) { OM_uint32 lmin; gss_buffer_desc msg = GSS_C_EMPTY_BUFFER; OM_uint32 ctx; struct sshbuf *b; char *ret; int r; if ((b = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); if (major_status != NULL) *major_status = ctxt->major; if (minor_status != NULL) *minor_status = ctxt->minor; ctx = 0; /* The GSSAPI error */ do { gss_display_status(&lmin, ctxt->major, GSS_C_GSS_CODE, ctxt->oid, &ctx, &msg); if ((r = sshbuf_put(b, msg.value, msg.length)) != 0 || (r = sshbuf_put_u8(b, '\n')) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); gss_release_buffer(&lmin, &msg); } while (ctx != 0); /* The mechanism specific error */ do { gss_display_status(&lmin, ctxt->minor, GSS_C_MECH_CODE, ctxt->oid, &ctx, &msg); if ((r = sshbuf_put(b, msg.value, msg.length)) != 0 || (r = sshbuf_put_u8(b, '\n')) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); gss_release_buffer(&lmin, &msg); } while (ctx != 0); if ((r = sshbuf_put_u8(b, '\n')) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); ret = xstrdup((const char *)sshbuf_ptr(b)); sshbuf_free(b); return (ret); }
/* * Caclulate a new key after a reconnect */ void calculate_new_key(u_int64_t *key, u_int64_t cookie, u_int64_t challenge) { int r; const EVP_MD *md = EVP_sha1(); EVP_MD_CTX ctx; char hash[EVP_MAX_MD_SIZE]; struct sshbuf *b; if ((b = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); if ((r = sshbuf_put_u64(b, *key)) != 0 || (r = sshbuf_put_u64(b, cookie)) != 0 || (r = sshbuf_put_u64(b, challenge)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); EVP_DigestInit(&ctx, md); EVP_DigestUpdate(&ctx, sshbuf_ptr(b), sshbuf_len(b)); EVP_DigestFinal(&ctx, hash, NULL); sshbuf_reset(b); if ((r = sshbuf_put(b, hash, EVP_MD_size(md))) != 0 || (r = sshbuf_get_u64(b, key)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); sshbuf_free(b); }
int kexc25519_shared_key_ext(const u_char key[CURVE25519_SIZE], const u_char pub[CURVE25519_SIZE], struct sshbuf *out, int raw) { u_char shared_key[CURVE25519_SIZE]; u_char zero[CURVE25519_SIZE]; int r; crypto_scalarmult_curve25519(shared_key, key, pub); /* Check for all-zero shared secret */ explicit_bzero(zero, CURVE25519_SIZE); if (timingsafe_bcmp(zero, shared_key, CURVE25519_SIZE) == 0) return SSH_ERR_KEY_INVALID_EC_VALUE; #ifdef DEBUG_KEXECDH dump_digest("shared secret", shared_key, CURVE25519_SIZE); #endif if (raw) r = sshbuf_put(out, shared_key, CURVE25519_SIZE); else r = sshbuf_put_bignum2_bytes(out, shared_key, CURVE25519_SIZE); explicit_bzero(shared_key, CURVE25519_SIZE); return r; }
int sshbuf_b64tod(struct sshbuf *buf, const char *b64) { size_t plen = strlen(b64); int nlen, r; u_char *p; if (plen == 0) return 0; if ((p = malloc(plen)) == NULL) return SSH_ERR_ALLOC_FAIL; if ((nlen = b64_pton(b64, p, plen)) < 0) { bzero(p, plen); free(p); return SSH_ERR_INVALID_FORMAT; } if ((r = sshbuf_put(buf, p, nlen)) < 0) { bzero(p, plen); free(p); return r; } bzero(p, plen); free(p); return 0; }
static int recv_msg(struct sshbuf *m) { u_int l, len; u_char c, buf[1024]; int r; if ((len = atomicio(read, fd, buf, 4)) != 4) { error("read from helper failed: %u", len); return (0); /* XXX */ } len = PEEK_U32(buf); if (len > 256 * 1024) fatal("response too long: %u", len); /* read len bytes into m */ sshbuf_reset(m); while (len > 0) { l = len; if (l > sizeof(buf)) l = sizeof(buf); if (atomicio(read, fd, buf, l) != l) { error("response from helper failed."); return (0); /* XXX */ } if ((r = sshbuf_put(m, buf, l)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); len -= l; } if ((r = sshbuf_get_u8(m, &c)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); return c; }
void buffer_append(Buffer *buffer, const void *data, u_int len) { int ret; if ((ret = sshbuf_put(buffer, data, len)) != 0) fatal("%s: %s", __func__, ssh_err(ret)); }
void dump_digest(char *msg, u_char *digest, int len) { struct sshbuf *b; fprintf(stderr, "%s\n", msg); if ((b = sshbuf_new()) == NULL) return; if (sshbuf_put(b, digest, len) == 0) sshbuf_dump(b, stderr); sshbuf_free(b); }
/* ARGSUSED */ int kex_input_kexinit(int type, u_int32_t seq, void *ctxt) { struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; const u_char *ptr; u_int i; size_t dlen; int r; debug("SSH2_MSG_KEXINIT received"); if (kex == NULL) return SSH_ERR_INVALID_ARGUMENT; ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, NULL); ptr = sshpkt_ptr(ssh, &dlen); if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0) return r; /* discard packet */ for (i = 0; i < KEX_COOKIE_LEN; i++) if ((r = sshpkt_get_u8(ssh, NULL)) != 0) return r; for (i = 0; i < PROPOSAL_MAX; i++) if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0) return r; /* * XXX RFC4253 sec 7: "each side MAY guess" - currently no supported * KEX method has the server move first, but a server might be using * a custom method or one that we otherwise don't support. We should * be prepared to remember first_kex_follows here so we can eat a * packet later. * XXX2 - RFC4253 is kind of ambiguous on what first_kex_follows means * for cases where the server *doesn't* go first. I guess we should * ignore it when it is set for these cases, which is what we do now. */ if ((r = sshpkt_get_u8(ssh, NULL)) != 0 || /* first_kex_follows */ (r = sshpkt_get_u32(ssh, NULL)) != 0 || /* reserved */ (r = sshpkt_get_end(ssh)) != 0) return r; if (!(kex->flags & KEX_INIT_SENT)) if ((r = kex_send_kexinit(ssh)) != 0) return r; if ((r = kex_choose_conf(ssh)) != 0) return r; if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL) return (kex->kex[kex->kex_type])(ssh); return SSH_ERR_INTERNAL_ERROR; }
/* Load a key from a fd into a buffer */ int sshkey_load_file(int fd, struct sshbuf *blob) { u_char buf[1024]; size_t len; struct stat st; int r, dontmax = 0; if (fstat(fd, &st) < 0) return SSH_ERR_SYSTEM_ERROR; if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 && st.st_size > MAX_KEY_FILE_SIZE) return SSH_ERR_INVALID_FORMAT; /* * Pre-allocate the buffer used for the key contents and clamp its * maximum size. This ensures that key contents are never leaked via * implicit realloc() in the sshbuf code. */ if ((st.st_mode & S_IFREG) == 0 || st.st_size <= 0) { st.st_size = 64*1024; /* 64k should be enough for anyone :) */ dontmax = 1; } if ((r = sshbuf_allocate(blob, st.st_size)) != 0 || (dontmax && (r = sshbuf_set_max_size(blob, st.st_size)) != 0)) return r; for (;;) { if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) { if (errno == EPIPE) break; r = SSH_ERR_SYSTEM_ERROR; goto out; } if ((r = sshbuf_put(blob, buf, len)) != 0) goto out; if (sshbuf_len(blob) > MAX_KEY_FILE_SIZE) { r = SSH_ERR_INVALID_FORMAT; goto out; } } if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 && st.st_size != (off_t)sshbuf_len(blob)) { r = SSH_ERR_FILE_CHANGED; goto out; } r = 0; out: explicit_bzero(buf, sizeof(buf)); if (r != 0) sshbuf_reset(blob); return r; }
/* convert SSH v2 key in OpenSSL PEM format */ static int sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *blob, const char *_passphrase, const char *comment) { int success, r; int blen, len = strlen(_passphrase); u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL; const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL; const u_char *bptr; BIO *bio = NULL; if (len > 0 && len <= 4) return SSH_ERR_PASSPHRASE_TOO_SHORT; if ((bio = BIO_new(BIO_s_mem())) == NULL) return SSH_ERR_ALLOC_FAIL; switch (key->type) { case KEY_DSA: success = PEM_write_bio_DSAPrivateKey(bio, key->dsa, cipher, passphrase, len, NULL, NULL); break; case KEY_ECDSA: success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa, cipher, passphrase, len, NULL, NULL); break; case KEY_RSA: success = PEM_write_bio_RSAPrivateKey(bio, key->rsa, cipher, passphrase, len, NULL, NULL); break; default: success = 0; break; } if (success == 0) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0) { r = SSH_ERR_INTERNAL_ERROR; goto out; } if ((r = sshbuf_put(blob, bptr, blen)) != 0) goto out; r = 0; out: BIO_free(bio); return r; }
static struct sshkey * keygrab_ssh1(con *c) { static struct sshkey *rsa; static struct sshbuf *msg; int r; u_char type; if (rsa == NULL) { if ((rsa = sshkey_new(KEY_RSA1)) == NULL) { error("%s: sshkey_new failed", __func__); return NULL; } if ((msg = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); } if ((r = sshbuf_put(msg, c->c_data, c->c_plen)) != 0 || (r = sshbuf_consume(msg, 8 - (c->c_plen & 7))) != 0 || /* padding */ (r = sshbuf_get_u8(msg, &type)) != 0) goto buf_err; if (type != (int) SSH_SMSG_PUBLIC_KEY) { error("%s: invalid packet type", c->c_name); sshbuf_reset(msg); return NULL; } if ((r = sshbuf_consume(msg, 8)) != 0 || /* cookie */ /* server key */ (r = sshbuf_get_u32(msg, NULL)) != 0 || (r = sshbuf_get_bignum1(msg, NULL)) != 0 || (r = sshbuf_get_bignum1(msg, NULL)) != 0 || /* host key */ (r = sshbuf_get_u32(msg, NULL)) != 0 || (r = sshbuf_get_bignum1(msg, rsa->rsa->e)) != 0 || (r = sshbuf_get_bignum1(msg, rsa->rsa->n)) != 0) { buf_err: error("%s: buffer error: %s", __func__, ssh_err(r)); sshbuf_reset(msg); return NULL; } sshbuf_reset(msg); return (rsa); }
/* Communicate with agent: send request and read reply */ static int ssh_request_reply(int sock, struct sshbuf *request, struct sshbuf *reply) { int r; size_t l, len; char buf[1024]; /* Get the length of the message, and format it in the buffer. */ len = sshbuf_len(request); put_u32(buf, len); /* Send the length and then the packet to the agent. */ if (atomicio(vwrite, sock, buf, 4) != 4 || atomicio(vwrite, sock, (u_char *)sshbuf_ptr(request), sshbuf_len(request)) != sshbuf_len(request)) return SSH_ERR_AGENT_COMMUNICATION; /* * Wait for response from the agent. First read the length of the * response packet. */ if (atomicio(read, sock, buf, 4) != 4) return SSH_ERR_AGENT_COMMUNICATION; /* Extract the length, and check it for sanity. */ len = get_u32(buf); if (len > MAX_AGENT_REPLY_LEN) return SSH_ERR_INVALID_FORMAT; /* Read the rest of the response in to the buffer. */ sshbuf_reset(reply); while (len > 0) { l = len; if (l > sizeof(buf)) l = sizeof(buf); if (atomicio(read, sock, buf, l) != l) return SSH_ERR_AGENT_COMMUNICATION; if ((r = sshbuf_put(reply, buf, l)) != 0) return r; len -= l; } return 0; }
/* ARGSUSED */ int kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh) { Kex *kex = ssh->kex; u_char *ptr; u_int i; size_t dlen; int r; debug("SSH2_MSG_KEXINIT received"); if (kex == NULL) return SSH_ERR_INVALID_ARGUMENT; ptr = sshpkt_ptr(ssh, &dlen); if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0) return r; /* discard packet */ for (i = 0; i < KEX_COOKIE_LEN; i++) if ((r = sshpkt_get_u8(ssh, NULL)) != 0) return r; for (i = 0; i < PROPOSAL_MAX; i++) if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0) return r; if ((r = sshpkt_get_u8(ssh, NULL)) != 0 || (r = sshpkt_get_u32(ssh, NULL)) != 0 || (r = sshpkt_get_end(ssh)) != 0) return r; if (!(kex->flags & KEX_INIT_SENT)) if ((r = kex_send_kexinit(ssh)) != 0) return r; if ((r = kex_choose_conf(ssh)) != 0) return r; if (kex->kex_type >= 0 && kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL) return (kex->kex[kex->kex_type])(ssh); return SSH_ERR_INTERNAL_ERROR; }
/* Load a key from a fd into a buffer */ int sshkey_load_file(int fd, struct sshbuf *blob) { u_char buf[1024]; size_t len; struct stat st; int r; if (fstat(fd, &st) < 0) return SSH_ERR_SYSTEM_ERROR; if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 && st.st_size > MAX_KEY_FILE_SIZE) return SSH_ERR_INVALID_FORMAT; for (;;) { if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) { if (errno == EPIPE) break; r = SSH_ERR_SYSTEM_ERROR; goto out; } if ((r = sshbuf_put(blob, buf, len)) != 0) goto out; if (sshbuf_len(blob) > MAX_KEY_FILE_SIZE) { r = SSH_ERR_INVALID_FORMAT; goto out; } } if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 && st.st_size != (off_t)sshbuf_len(blob)) { r = SSH_ERR_FILE_CHANGED; goto out; } r = 0; out: explicit_bzero(buf, sizeof(buf)); if (r != 0) sshbuf_reset(blob); return r; }
static void attempt_parse_blob(u_char *blob, size_t len) { struct sshbuf *p1; BIGNUM *bn; #ifdef OPENSSL_HAS_NISTP256 EC_KEY *eck; #endif u_char *s; size_t l; u_int8_t u8; u_int16_t u16; u_int32_t u32; u_int64_t u64; p1 = sshbuf_new(); ASSERT_PTR_NE(p1, NULL); ASSERT_INT_EQ(sshbuf_put(p1, blob, len), 0); sshbuf_get_u8(p1, &u8); sshbuf_get_u16(p1, &u16); sshbuf_get_u32(p1, &u32); sshbuf_get_u64(p1, &u64); if (sshbuf_get_string(p1, &s, &l) == 0) { bzero(s, l); free(s); } bn = BN_new(); sshbuf_get_bignum1(p1, bn); BN_clear_free(bn); bn = BN_new(); sshbuf_get_bignum2(p1, bn); BN_clear_free(bn); #ifdef OPENSSL_HAS_NISTP256 eck = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); ASSERT_PTR_NE(eck, NULL); sshbuf_get_eckey(p1, eck); EC_KEY_free(eck); #endif sshbuf_free(p1); }
int ssh_decrypt_challenge(int sock, struct sshkey* key, BIGNUM *challenge, u_char session_id[16], u_char response[16]) { struct sshbuf *msg; int r; u_char type; if (key->type != KEY_RSA1) return SSH_ERR_INVALID_ARGUMENT; if ((msg = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_put_u8(msg, SSH_AGENTC_RSA_CHALLENGE)) != 0 || (r = sshbuf_put_u32(msg, BN_num_bits(key->rsa->n))) != 0 || (r = sshbuf_put_bignum1(msg, key->rsa->e)) != 0 || (r = sshbuf_put_bignum1(msg, key->rsa->n)) != 0 || (r = sshbuf_put_bignum1(msg, challenge)) != 0 || (r = sshbuf_put(msg, session_id, 16)) != 0 || (r = sshbuf_put_u32(msg, 1)) != 0) /* Response type for proto 1.1 */ goto out; if ((r = ssh_request_reply(sock, msg, msg)) != 0) goto out; if ((r = sshbuf_get_u8(msg, &type)) != 0) goto out; if (agent_failed(type)) { r = SSH_ERR_AGENT_FAILURE; goto out; } else if (type != SSH_AGENT_RSA_RESPONSE) { r = SSH_ERR_INVALID_FORMAT; goto out; } if ((r = sshbuf_get(msg, response, 16)) != 0) goto out; r = 0; out: sshbuf_free(msg); return r; }
/* * Caclulate a new key after a reconnect */ void calculate_new_key(u_int64_t *key, u_int64_t cookie, u_int64_t challenge) { u_char hash[SSH_DIGEST_MAX_LENGTH]; struct sshbuf *b; int r; if ((b = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); if ((r = sshbuf_put_u64(b, *key)) != 0 || (r = sshbuf_put_u64(b, cookie)) != 0 || (r = sshbuf_put_u64(b, challenge)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (ssh_digest_buffer(SSH_DIGEST_SHA1, b, hash, sizeof(hash)) != 0) fatal("%s: digest_buffer failed", __func__); sshbuf_reset(b); if ((r = sshbuf_put(b, hash, ssh_digest_bytes(SSH_DIGEST_SHA1))) != 0 || (r = sshbuf_get_u64(b, key)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); sshbuf_free(b); }
static int server_input_stdin_data(int type, u_int32_t seq, struct ssh *ssh) { u_char *data = NULL; size_t data_len; int r; /* Stdin data from the client. Append it to the buffer. */ /* Ignore any data if the client has closed stdin. */ if (fdin == -1) return 0; if ((r = sshpkt_get_string(ssh, &data, &data_len)) != 0 || (r = sshpkt_get_end(ssh)) != 0 || (r = sshbuf_put(stdin_buffer, data, data_len)) != 0) goto out; r = 0; out: if (data) { explicit_bzero(data, data_len); free(data); } return r; }
int sshbuf_putb(struct sshbuf *buf, const struct sshbuf *v) { return sshbuf_put(buf, sshbuf_ptr(v), sshbuf_len(v)); }
static int derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen, const u_char *shared_secret, u_int slen, u_char **keyp) { struct kex *kex = ssh->kex; struct sshbuf *b = NULL; struct ssh_digest_ctx *hashctx = NULL; char c = id; u_int have; size_t mdsz; u_char *digest; int r; if ((mdsz = ssh_digest_bytes(kex->hash_alg)) == 0) return SSH_ERR_INVALID_ARGUMENT; if ((digest = calloc(1, roundup(need, mdsz))) == NULL || (b = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshbuf_put(b, shared_secret, slen)) < 0) goto out; /* K1 = HASH(K || H || "A" || session_id) */ if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL || ssh_digest_update_buffer(hashctx, b) != 0 || ssh_digest_update(hashctx, hash, hashlen) != 0 || ssh_digest_update(hashctx, &c, 1) != 0 || ssh_digest_update(hashctx, kex->session_id, kex->session_id_len) != 0 || ssh_digest_final(hashctx, digest, mdsz) != 0) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } ssh_digest_free(hashctx); hashctx = NULL; /* * expand key: * Kn = HASH(K || H || K1 || K2 || ... || Kn-1) * Key = K1 || K2 || ... || Kn */ for (have = mdsz; need > have; have += mdsz) { if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL || ssh_digest_update_buffer(hashctx, b) != 0 || ssh_digest_update(hashctx, hash, hashlen) != 0 || ssh_digest_update(hashctx, digest, have) != 0 || ssh_digest_final(hashctx, digest + have, mdsz) != 0) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } ssh_digest_free(hashctx); hashctx = NULL; } #ifdef DEBUG_KEX fprintf(stderr, "key '%c'== ", c); dump_digest("key", digest, need); #endif *keyp = digest; digest = NULL; r = 0; out: if (digest) free(digest); if (b) sshbuf_free(b); ssh_digest_free(hashctx); return r; }
void sshbuf_getput_crypto_tests(void) { struct sshbuf *p1; const u_char *d; size_t s; BIGNUM *bn, *bn2, *bn_x, *bn_y; /* This one has num_bits != num_bytes * 8 to test bignum1 encoding */ const char *hexbn1 = "0102030405060708090a0b0c0d0e0f10"; /* This one has MSB set to test bignum2 encoding negative-avoidance */ const char *hexbn2 = "f0e0d0c0b0a0908070605040302010007fff11"; u_char expbn1[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, }; u_char expbn2[] = { 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, 0x90, 0x80, 0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00, 0x7f, 0xff, 0x11 }; int ec256_nid = NID_X9_62_prime256v1; char *ec256_x = "0C828004839D0106AA59575216191357" "34B451459DADB586677EF9DF55784999"; char *ec256_y = "4D196B50F0B4E94B3C73E3A9D4CD9DF2" "C8F9A35E42BDD047550F69D80EC23CD4"; u_char expec256[] = { 0x04, 0x0c, 0x82, 0x80, 0x04, 0x83, 0x9d, 0x01, 0x06, 0xaa, 0x59, 0x57, 0x52, 0x16, 0x19, 0x13, 0x57, 0x34, 0xb4, 0x51, 0x45, 0x9d, 0xad, 0xb5, 0x86, 0x67, 0x7e, 0xf9, 0xdf, 0x55, 0x78, 0x49, 0x99, 0x4d, 0x19, 0x6b, 0x50, 0xf0, 0xb4, 0xe9, 0x4b, 0x3c, 0x73, 0xe3, 0xa9, 0xd4, 0xcd, 0x9d, 0xf2, 0xc8, 0xf9, 0xa3, 0x5e, 0x42, 0xbd, 0xd0, 0x47, 0x55, 0x0f, 0x69, 0xd8, 0x0e, 0xc2, 0x3c, 0xd4 }; EC_KEY *eck; EC_POINT *ecp; int r; #define MKBN(b, bnn) \ do { \ bnn = NULL; \ ASSERT_INT_GT(BN_hex2bn(&bnn, b), 0); \ } while (0) TEST_START("sshbuf_put_bignum1"); MKBN(hexbn1, bn); p1 = sshbuf_new(); ASSERT_PTR_NE(p1, NULL); ASSERT_INT_EQ(sshbuf_put_bignum1(p1, bn), 0); ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn1) + 2); ASSERT_U16_EQ(PEEK_U16(sshbuf_ptr(p1)), (u_int16_t)BN_num_bits(bn)); ASSERT_MEM_EQ(sshbuf_ptr(p1) + 2, expbn1, sizeof(expbn1)); BN_free(bn); sshbuf_free(p1); TEST_DONE(); TEST_START("sshbuf_put_bignum1 limited"); MKBN(hexbn1, bn); p1 = sshbuf_new(); ASSERT_PTR_NE(p1, NULL); ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(expbn1) + 1), 0); r = sshbuf_put_bignum1(p1, bn); ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); BN_free(bn); sshbuf_free(p1); TEST_DONE(); TEST_START("sshbuf_put_bignum1 bn2"); MKBN(hexbn2, bn); p1 = sshbuf_new(); ASSERT_PTR_NE(p1, NULL); ASSERT_INT_EQ(sshbuf_put_bignum1(p1, bn), 0); ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn2) + 2); ASSERT_U16_EQ(PEEK_U16(sshbuf_ptr(p1)), (u_int16_t)BN_num_bits(bn)); ASSERT_MEM_EQ(sshbuf_ptr(p1) + 2, expbn2, sizeof(expbn2)); BN_free(bn); sshbuf_free(p1); TEST_DONE(); TEST_START("sshbuf_put_bignum1 bn2 limited"); MKBN(hexbn2, bn); p1 = sshbuf_new(); ASSERT_PTR_NE(p1, NULL); ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(expbn1) + 1), 0); r = sshbuf_put_bignum1(p1, bn); ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); BN_free(bn); sshbuf_free(p1); TEST_DONE(); TEST_START("sshbuf_put_bignum2"); MKBN(hexbn1, bn); p1 = sshbuf_new(); ASSERT_PTR_NE(p1, NULL); ASSERT_INT_EQ(sshbuf_put_bignum2(p1, bn), 0); ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn1) + 4); ASSERT_U32_EQ(PEEK_U32(sshbuf_ptr(p1)), (u_int32_t)BN_num_bytes(bn)); ASSERT_MEM_EQ(sshbuf_ptr(p1) + 4, expbn1, sizeof(expbn1)); BN_free(bn); sshbuf_free(p1); TEST_DONE(); TEST_START("sshbuf_put_bignum2 limited"); MKBN(hexbn1, bn); p1 = sshbuf_new(); ASSERT_PTR_NE(p1, NULL); ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(expbn1) + 3), 0); r = sshbuf_put_bignum2(p1, bn); ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); BN_free(bn); sshbuf_free(p1); TEST_DONE(); TEST_START("sshbuf_put_bignum2 bn2"); MKBN(hexbn2, bn); p1 = sshbuf_new(); ASSERT_PTR_NE(p1, NULL); ASSERT_INT_EQ(sshbuf_put_bignum2(p1, bn), 0); ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn2) + 4 + 1); /* MSB */ ASSERT_U32_EQ(PEEK_U32(sshbuf_ptr(p1)), (u_int32_t)BN_num_bytes(bn) + 1); ASSERT_U8_EQ(*(sshbuf_ptr(p1) + 4), 0x00); ASSERT_MEM_EQ(sshbuf_ptr(p1) + 5, expbn2, sizeof(expbn2)); BN_free(bn); sshbuf_free(p1); TEST_DONE(); TEST_START("sshbuf_put_bignum2 bn2 limited"); MKBN(hexbn2, bn); p1 = sshbuf_new(); ASSERT_PTR_NE(p1, NULL); ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(expbn2) + 3), 0); r = sshbuf_put_bignum2(p1, bn); ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); BN_free(bn); sshbuf_free(p1); TEST_DONE(); TEST_START("sshbuf_get_bignum1"); MKBN(hexbn1, bn); p1 = sshbuf_new(); ASSERT_PTR_NE(p1, NULL); ASSERT_INT_EQ(sshbuf_put_u16(p1, BN_num_bits(bn)), 0); ASSERT_INT_EQ(sshbuf_put(p1, expbn1, sizeof(expbn1)), 0); ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn1)); ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xd00f), 0); bn2 = BN_new(); ASSERT_INT_EQ(sshbuf_get_bignum1(p1, bn2), 0); ASSERT_BIGNUM_EQ(bn, bn2); ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); BN_free(bn); BN_free(bn2); sshbuf_free(p1); TEST_DONE(); TEST_START("sshbuf_get_bignum1 truncated"); MKBN(hexbn1, bn); p1 = sshbuf_new(); ASSERT_PTR_NE(p1, NULL); ASSERT_INT_EQ(sshbuf_put_u16(p1, BN_num_bits(bn)), 0); ASSERT_INT_EQ(sshbuf_put(p1, expbn1, sizeof(expbn1) - 1), 0); ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn1) - 1); bn2 = BN_new(); r = sshbuf_get_bignum1(p1, bn2); ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn1) - 1); BN_free(bn); BN_free(bn2); sshbuf_free(p1); TEST_DONE(); TEST_START("sshbuf_get_bignum1 giant"); MKBN(hexbn1, bn); p1 = sshbuf_new(); ASSERT_PTR_NE(p1, NULL); ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xffff), 0); ASSERT_INT_EQ(sshbuf_reserve(p1, (0xffff + 7) / 8, NULL), 0); ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + ((0xffff + 7) / 8)); bn2 = BN_new(); r = sshbuf_get_bignum1(p1, bn2); ASSERT_INT_EQ(r, SSH_ERR_BIGNUM_TOO_LARGE); ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + ((0xffff + 7) / 8)); BN_free(bn); BN_free(bn2); sshbuf_free(p1); TEST_DONE(); TEST_START("sshbuf_get_bignum1 bn2"); MKBN(hexbn2, bn); p1 = sshbuf_new(); ASSERT_PTR_NE(p1, NULL); ASSERT_INT_EQ(sshbuf_put_u16(p1, BN_num_bits(bn)), 0); ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2)), 0); ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn2)); ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xd00f), 0); bn2 = BN_new(); ASSERT_INT_EQ(sshbuf_get_bignum1(p1, bn2), 0); ASSERT_BIGNUM_EQ(bn, bn2); ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); BN_free(bn); BN_free(bn2); sshbuf_free(p1); TEST_DONE(); TEST_START("sshbuf_get_bignum1 bn2 truncated"); MKBN(hexbn2, bn); p1 = sshbuf_new(); ASSERT_PTR_NE(p1, NULL); ASSERT_INT_EQ(sshbuf_put_u16(p1, BN_num_bits(bn)), 0); ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2) - 1), 0); ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn2) - 1); bn2 = BN_new(); r = sshbuf_get_bignum1(p1, bn2); ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn2) - 1); BN_free(bn); BN_free(bn2); sshbuf_free(p1); TEST_DONE(); TEST_START("sshbuf_get_bignum2"); MKBN(hexbn1, bn); p1 = sshbuf_new(); ASSERT_PTR_NE(p1, NULL); ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn)), 0); ASSERT_INT_EQ(sshbuf_put(p1, expbn1, sizeof(expbn1)), 0); ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4 + sizeof(expbn1)); ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xd00f), 0); bn2 = BN_new(); ASSERT_INT_EQ(sshbuf_get_bignum2(p1, bn2), 0); ASSERT_BIGNUM_EQ(bn, bn2); ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); BN_free(bn); BN_free(bn2); sshbuf_free(p1); TEST_DONE(); TEST_START("sshbuf_get_bignum2 truncated"); MKBN(hexbn1, bn); p1 = sshbuf_new(); ASSERT_PTR_NE(p1, NULL); ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn)), 0); ASSERT_INT_EQ(sshbuf_put(p1, expbn1, sizeof(expbn1) - 1), 0); bn2 = BN_new(); r = sshbuf_get_bignum2(p1, bn2); ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn1) + 3); BN_free(bn); BN_free(bn2); sshbuf_free(p1); TEST_DONE(); TEST_START("sshbuf_get_bignum2 giant"); MKBN(hexbn1, bn); p1 = sshbuf_new(); ASSERT_PTR_NE(p1, NULL); ASSERT_INT_EQ(sshbuf_put_u32(p1, 65536), 0); ASSERT_INT_EQ(sshbuf_reserve(p1, 65536, NULL), 0); bn2 = BN_new(); r = sshbuf_get_bignum2(p1, bn2); ASSERT_INT_EQ(r, SSH_ERR_BIGNUM_TOO_LARGE); ASSERT_SIZE_T_EQ(sshbuf_len(p1), 65536 + 4); BN_free(bn); BN_free(bn2); sshbuf_free(p1); TEST_DONE(); TEST_START("sshbuf_get_bignum2 bn2"); MKBN(hexbn2, bn); p1 = sshbuf_new(); ASSERT_PTR_NE(p1, NULL); ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn) + 1), 0); /* MSB */ ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x00), 0); ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2)), 0); ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4 + 1 + sizeof(expbn2)); ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xd00f), 0); bn2 = BN_new(); ASSERT_INT_EQ(sshbuf_get_bignum2(p1, bn2), 0); ASSERT_BIGNUM_EQ(bn, bn2); ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2); BN_free(bn); BN_free(bn2); sshbuf_free(p1); TEST_DONE(); TEST_START("sshbuf_get_bignum2 bn2 truncated"); MKBN(hexbn2, bn); p1 = sshbuf_new(); ASSERT_PTR_NE(p1, NULL); ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn) + 1), 0); ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x00), 0); ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2) - 1), 0); bn2 = BN_new(); r = sshbuf_get_bignum2(p1, bn2); ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE); ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn2) + 1 + 4 - 1); BN_free(bn); BN_free(bn2); sshbuf_free(p1); TEST_DONE(); TEST_START("sshbuf_get_bignum2 bn2 negative"); MKBN(hexbn2, bn); p1 = sshbuf_new(); ASSERT_PTR_NE(p1, NULL); ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn)), 0); ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2)), 0); bn2 = BN_new(); r = sshbuf_get_bignum2(p1, bn2); ASSERT_INT_EQ(r, SSH_ERR_BIGNUM_IS_NEGATIVE); ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn2) + 4); BN_free(bn); BN_free(bn2); sshbuf_free(p1); TEST_DONE(); TEST_START("sshbuf_put_ec"); eck = EC_KEY_new_by_curve_name(ec256_nid); ASSERT_PTR_NE(eck, NULL); ecp = EC_POINT_new(EC_KEY_get0_group(eck)); ASSERT_PTR_NE(ecp, NULL); MKBN(ec256_x, bn_x); MKBN(ec256_y, bn_y); ASSERT_INT_EQ(EC_POINT_set_affine_coordinates_GFp( EC_KEY_get0_group(eck), ecp, bn_x, bn_y, NULL), 1); ASSERT_INT_EQ(EC_KEY_set_public_key(eck, ecp), 1); EC_POINT_free(ecp); p1 = sshbuf_new(); ASSERT_PTR_NE(p1, NULL); ASSERT_INT_EQ(sshbuf_put_eckey(p1, eck), 0); ASSERT_INT_EQ(sshbuf_get_string_direct(p1, &d, &s), 0); ASSERT_SIZE_T_EQ(s, sizeof(expec256)); ASSERT_MEM_EQ(d, expec256, sizeof(expec256)); sshbuf_free(p1); EC_KEY_free(eck); TEST_DONE(); TEST_START("sshbuf_get_ec"); eck = EC_KEY_new_by_curve_name(ec256_nid); ASSERT_PTR_NE(eck, NULL); p1 = sshbuf_new(); ASSERT_PTR_NE(p1, NULL); ASSERT_INT_EQ(sshbuf_put_string(p1, expec256, sizeof(expec256)), 0); ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expec256) + 4); ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x00), 0); ASSERT_INT_EQ(sshbuf_get_eckey(p1, eck), 0); bn_x = BN_new(); bn_y = BN_new(); ASSERT_PTR_NE(bn_x, NULL); ASSERT_PTR_NE(bn_y, NULL); ASSERT_INT_EQ(EC_POINT_get_affine_coordinates_GFp( EC_KEY_get0_group(eck), EC_KEY_get0_public_key(eck), bn_x, bn_y, NULL), 1); MKBN(ec256_x, bn); MKBN(ec256_y, bn2); ASSERT_INT_EQ(BN_cmp(bn_x, bn), 0); ASSERT_INT_EQ(BN_cmp(bn_y, bn2), 0); ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1); sshbuf_free(p1); EC_KEY_free(eck); BN_free(bn_x); BN_free(bn_y); BN_free(bn); BN_free(bn2); TEST_DONE(); }
int ssh_dss_verify(const struct sshkey *key, const u_char *signature, u_int signaturelen, const u_char *data, u_int datalen, u_int compat) { DSA_SIG *sig = NULL; const EVP_MD *evp_md = EVP_sha1(); EVP_MD_CTX md; u_char digest[EVP_MAX_MD_SIZE], *sigblob = NULL; size_t len; u_int dlen; int ret = SSH_ERR_INTERNAL_ERROR; struct sshbuf *b = NULL; char *ktype = NULL; if (key == NULL || key->dsa == NULL || (key->type != KEY_DSA && key->type != KEY_DSA_CERT && key->type != KEY_DSA_CERT_V00)) return SSH_ERR_INVALID_ARGUMENT; /* fetch signature */ if (compat & SSH_BUG_SIGBLOB) { if ((sigblob = malloc(signaturelen)) == NULL) return SSH_ERR_ALLOC_FAIL; memcpy(sigblob, signature, signaturelen); len = signaturelen; } else { /* ietf-drafts */ if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((ret = sshbuf_put(b, signature, signaturelen)) != 0) goto out; if (sshbuf_get_cstring(b, &ktype, NULL) != 0 || sshbuf_get_string(b, &sigblob, &len) != 0) { ret = SSH_ERR_INVALID_FORMAT; goto out; } if (strcmp("ssh-dss", ktype) != 0) { ret = SSH_ERR_KEY_TYPE_MISMATCH; goto out; } if (sshbuf_len(b) != 0) { ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; goto out; } } if (len != SIGBLOB_LEN) { ret = SSH_ERR_INVALID_FORMAT; goto out; } /* parse signature */ if ((sig = DSA_SIG_new()) == NULL || (sig->r = BN_new()) == NULL || (sig->s = BN_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } if ((BN_bin2bn(sigblob, INTBLOB_LEN, sig->r) == NULL) || (BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s) == NULL)) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } /* sha1 the data */ if (EVP_DigestInit(&md, evp_md) != 1 || EVP_DigestUpdate(&md, data, datalen) != 1 || EVP_DigestFinal(&md, digest, &dlen) != 1) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } switch (DSA_do_verify(digest, dlen, sig, key->dsa)) { case 1: ret = 0; break; case 0: ret = SSH_ERR_SIGNATURE_INVALID; goto out; default: ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } out: bzero(digest, sizeof(digest)); bzero(&md, sizeof(md)); if (sig != NULL) DSA_SIG_free(sig); if (b != NULL) sshbuf_free(b); if (ktype != NULL) free(ktype); if (sigblob != NULL) { memset(sigblob, 0, len); free(sigblob); } return ret; }
int sftp_server_main(int argc, char **argv, struct passwd *user_pw) { fd_set *rset, *wset; int i, r, in, out, max, ch, skipargs = 0, log_stderr = 0; ssize_t len, olen, set_size; SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; char *cp, *homedir = NULL, buf[4*4096]; long mask; extern char *optarg; extern char *__progname; ssh_malloc_init(); /* must be called before any mallocs */ __progname = ssh_get_progname(argv[0]); log_init(__progname, log_level, log_facility, log_stderr); pw = pwcopy(user_pw); while (!skipargs && (ch = getopt(argc, argv, "d:f:l:P:p:Q:u:cehR")) != -1) { switch (ch) { case 'Q': if (strcasecmp(optarg, "requests") != 0) { fprintf(stderr, "Invalid query type\n"); exit(1); } for (i = 0; handlers[i].handler != NULL; i++) printf("%s\n", handlers[i].name); for (i = 0; extended_handlers[i].handler != NULL; i++) printf("%s\n", extended_handlers[i].name); exit(0); break; case 'R': readonly = 1; break; case 'c': /* * Ignore all arguments if we are invoked as a * shell using "sftp-server -c command" */ skipargs = 1; break; case 'e': log_stderr = 1; break; case 'l': log_level = log_level_number(optarg); if (log_level == SYSLOG_LEVEL_NOT_SET) error("Invalid log level \"%s\"", optarg); break; case 'f': log_facility = log_facility_number(optarg); if (log_facility == SYSLOG_FACILITY_NOT_SET) error("Invalid log facility \"%s\"", optarg); break; case 'd': cp = tilde_expand_filename(optarg, user_pw->pw_uid); homedir = percent_expand(cp, "d", user_pw->pw_dir, "u", user_pw->pw_name, (char *)NULL); free(cp); break; case 'p': if (request_whitelist != NULL) fatal("Permitted requests already set"); request_whitelist = xstrdup(optarg); break; case 'P': if (request_blacklist != NULL) fatal("Refused requests already set"); request_blacklist = xstrdup(optarg); break; case 'u': errno = 0; mask = strtol(optarg, &cp, 8); if (mask < 0 || mask > 0777 || *cp != '\0' || cp == optarg || (mask == 0 && errno != 0)) fatal("Invalid umask \"%s\"", optarg); (void)umask((mode_t)mask); break; case 'h': default: sftp_server_usage(); } } log_init(__progname, log_level, log_facility, log_stderr); #if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE) /* * On Linux, we should try to avoid making /proc/self/{mem,maps} * available to the user so that sftp access doesn't automatically * imply arbitrary code execution access that will break * restricted configurations. */ if (prctl(PR_SET_DUMPABLE, 0) != 0) fatal("unable to make the process undumpable"); #endif /* defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE) */ /* Drop any fine-grained privileges we don't need */ platform_pledge_sftp_server(); if ((cp = getenv("SSH_CONNECTION")) != NULL) { client_addr = xstrdup(cp); if ((cp = strchr(client_addr, ' ')) == NULL) { error("Malformed SSH_CONNECTION variable: \"%s\"", getenv("SSH_CONNECTION")); sftp_server_cleanup_exit(255); } *cp = '\0'; } else client_addr = xstrdup("UNKNOWN"); logit("session opened for local user %s from [%s]", pw->pw_name, client_addr); in = STDIN_FILENO; out = STDOUT_FILENO; #ifdef HAVE_CYGWIN setmode(in, O_BINARY); setmode(out, O_BINARY); #endif max = 0; if (in > max) max = in; if (out > max) max = out; if ((iqueue = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); if ((oqueue = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); rset = xcalloc(howmany(max + 1, NFDBITS), sizeof(fd_mask)); wset = xcalloc(howmany(max + 1, NFDBITS), sizeof(fd_mask)); if (homedir != NULL) { if (chdir(homedir) != 0) { error("chdir to \"%s\" failed: %s", homedir, strerror(errno)); } } set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask); for (;;) { memset(rset, 0, set_size); memset(wset, 0, set_size); /* * Ensure that we can read a full buffer and handle * the worst-case length packet it can generate, * otherwise apply backpressure by stopping reads. */ if ((r = sshbuf_check_reserve(iqueue, sizeof(buf))) == 0 && (r = sshbuf_check_reserve(oqueue, SFTP_MAX_MSG_LENGTH)) == 0) FD_SET(in, rset); else if (r != SSH_ERR_NO_BUFFER_SPACE) fatal("%s: sshbuf_check_reserve failed: %s", __func__, ssh_err(r)); olen = sshbuf_len(oqueue); if (olen > 0) FD_SET(out, wset); if (select(max+1, rset, wset, NULL, NULL) < 0) { if (errno == EINTR) continue; error("select: %s", strerror(errno)); sftp_server_cleanup_exit(2); } /* copy stdin to iqueue */ if (FD_ISSET(in, rset)) { len = read(in, buf, sizeof buf); if (len == 0) { debug("read eof"); sftp_server_cleanup_exit(0); } else if (len < 0) { error("read: %s", strerror(errno)); sftp_server_cleanup_exit(1); } else if ((r = sshbuf_put(iqueue, buf, len)) != 0) { fatal("%s: buffer error: %s", __func__, ssh_err(r)); } } /* send oqueue to stdout */ if (FD_ISSET(out, wset)) { len = write(out, sshbuf_ptr(oqueue), olen); if (len < 0) { error("write: %s", strerror(errno)); sftp_server_cleanup_exit(1); } else if ((r = sshbuf_consume(oqueue, len)) != 0) { fatal("%s: buffer error: %s", __func__, ssh_err(r)); } } /* * Process requests from client if we can fit the results * into the output buffer, otherwise stop processing input * and let the output queue drain. */ r = sshbuf_check_reserve(oqueue, SFTP_MAX_MSG_LENGTH); if (r == 0) process(); else if (r != SSH_ERR_NO_BUFFER_SPACE) fatal("%s: sshbuf_check_reserve: %s", __func__, ssh_err(r)); } }
void userauth_finish(struct ssh *ssh, int authenticated, const char *method, const char *submethod) { Authctxt *authctxt = ssh->authctxt; char *methods; int partial = 0; if (!authctxt->valid && authenticated) fatal("INTERNAL ERROR: authenticated invalid user %s", authctxt->user); if (authenticated && authctxt->postponed) fatal("INTERNAL ERROR: authenticated and postponed"); /* Special handling for root */ if (authenticated && authctxt->pw->pw_uid == 0 && !auth_root_allowed(ssh, method)) { authenticated = 0; #ifdef SSH_AUDIT_EVENTS PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED)); #endif } if (authenticated && options.num_auth_methods != 0) { if (!auth2_update_methods_lists(authctxt, method, submethod)) { authenticated = 0; partial = 1; } } /* Log before sending the reply */ auth_log(authctxt, authenticated, partial, method, submethod); /* Update information exposed to session */ if (authenticated || partial) auth2_update_session_info(authctxt, method, submethod); if (authctxt->postponed) return; #ifdef USE_PAM if (options.use_pam && authenticated) { int r; if (!PRIVSEP(do_pam_account())) { /* if PAM returned a message, send it to the user */ if (sshbuf_len(loginmsg) > 0) { if ((r = sshbuf_put(loginmsg, "\0", 1)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); userauth_send_banner(sshbuf_ptr(loginmsg)); packet_write_wait(); } fatal("Access denied for user %s by PAM account " "configuration", authctxt->user); } } #endif if (authenticated == 1) { /* turn off userauth */ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore); packet_start(SSH2_MSG_USERAUTH_SUCCESS); packet_send(); packet_write_wait(); /* now we can break out */ authctxt->success = 1; ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user); } else { /* Allow initial try of "none" auth without failure penalty */ if (!partial && !authctxt->server_caused_failure && (authctxt->attempt > 1 || strcmp(method, "none") != 0)) authctxt->failures++; if (authctxt->failures >= options.max_authtries) { #ifdef SSH_AUDIT_EVENTS PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES)); #endif auth_maxtries_exceeded(authctxt); } methods = authmethods_get(authctxt); debug3("%s: failure partial=%d next methods=\"%s\"", __func__, partial, methods); packet_start(SSH2_MSG_USERAUTH_FAILURE); packet_put_cstring(methods); packet_put_char(partial); packet_send(); packet_write_wait(); free(methods); } }
/* * Serialises the authentication (private) key to a blob, encrypting it with * passphrase. The identification of the blob (lowest 64 bits of n) will * precede the key to provide identification of the key without needing a * passphrase. */ static int sshkey_private_rsa1_to_blob(struct sshkey *key, struct sshbuf *blob, const char *passphrase, const char *comment) { struct sshbuf *buffer = NULL, *encrypted = NULL; u_char buf[8]; int r, cipher_num; struct sshcipher_ctx ciphercontext; const struct sshcipher *cipher; u_char *cp; /* * If the passphrase is empty, use SSH_CIPHER_NONE to ease converting * to another cipher; otherwise use SSH_AUTHFILE_CIPHER. */ cipher_num = (strcmp(passphrase, "") == 0) ? SSH_CIPHER_NONE : SSH_AUTHFILE_CIPHER; if ((cipher = cipher_by_number(cipher_num)) == NULL) return SSH_ERR_INTERNAL_ERROR; /* This buffer is used to build the secret part of the private key. */ if ((buffer = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; /* Put checkbytes for checking passphrase validity. */ if ((r = sshbuf_reserve(buffer, 4, &cp)) != 0) goto out; arc4random_buf(cp, 2); memcpy(cp + 2, cp, 2); /* * Store the private key (n and e will not be stored because they * will be stored in plain text, and storing them also in encrypted * format would just give known plaintext). * Note: q and p are stored in reverse order to SSL. */ if ((r = sshbuf_put_bignum1(buffer, key->rsa->d)) != 0 || (r = sshbuf_put_bignum1(buffer, key->rsa->iqmp)) != 0 || (r = sshbuf_put_bignum1(buffer, key->rsa->q)) != 0 || (r = sshbuf_put_bignum1(buffer, key->rsa->p)) != 0) goto out; /* Pad the part to be encrypted to a size that is a multiple of 8. */ bzero(buf, 8); if ((r = sshbuf_put(buffer, buf, 8 - (sshbuf_len(buffer) % 8))) != 0) goto out; /* This buffer will be used to contain the data in the file. */ if ((encrypted = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } /* First store keyfile id string. */ if ((r = sshbuf_put(encrypted, authfile_id_string, sizeof(authfile_id_string))) != 0) goto out; /* Store cipher type and "reserved" field. */ if ((r = sshbuf_put_u8(encrypted, cipher_num)) != 0 || (r = sshbuf_put_u32(encrypted, 0)) != 0) goto out; /* Store public key. This will be in plain text. */ if ((r = sshbuf_put_u32(encrypted, BN_num_bits(key->rsa->n))) != 0 || (r = sshbuf_put_bignum1(encrypted, key->rsa->n) != 0) || (r = sshbuf_put_bignum1(encrypted, key->rsa->e) != 0) || (r = sshbuf_put_cstring(encrypted, comment) != 0)) goto out; /* Allocate space for the private part of the key in the buffer. */ if ((r = sshbuf_reserve(encrypted, sshbuf_len(buffer), &cp)) != 0) goto out; if ((r = cipher_set_key_string(&ciphercontext, cipher, passphrase, CIPHER_ENCRYPT)) != 0) goto out; if ((r = cipher_crypt(&ciphercontext, cp, sshbuf_ptr(buffer), sshbuf_len(buffer), 0, 0)) != 0) goto out; if ((r = cipher_cleanup(&ciphercontext)) != 0) goto out; r = sshbuf_putb(blob, encrypted); out: bzero(&ciphercontext, sizeof(ciphercontext)); bzero(buf, sizeof(buf)); if (buffer != NULL) sshbuf_free(buffer); if (encrypted != NULL) sshbuf_free(encrypted); return r; }
void sshkey_fuzz_tests(void) { struct sshkey *k1; struct sshbuf *buf, *fuzzed; struct fuzz *fuzz; int r; TEST_START("fuzz RSA1 private"); buf = load_file("rsa1_1"); fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP | FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END, sshbuf_mutable_ptr(buf), sshbuf_len(buf)); ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", &k1, NULL), 0); sshkey_free(k1); sshbuf_free(buf); ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); TEST_ONERROR(onerror, fuzz); for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); ASSERT_INT_EQ(r, 0); if (sshkey_parse_private_fileblob(fuzzed, "", "key", &k1, NULL) == 0) sshkey_free(k1); sshbuf_reset(fuzzed); } sshbuf_free(fuzzed); fuzz_cleanup(fuzz); TEST_DONE(); TEST_START("fuzz RSA1 public"); buf = load_file("rsa1_1_pw"); fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP | FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END, sshbuf_mutable_ptr(buf), sshbuf_len(buf)); ASSERT_INT_EQ(sshkey_parse_public_rsa1_fileblob(buf, &k1, NULL), 0); sshkey_free(k1); sshbuf_free(buf); ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); TEST_ONERROR(onerror, fuzz); for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); ASSERT_INT_EQ(r, 0); if (sshkey_parse_public_rsa1_fileblob(fuzzed, &k1, NULL) == 0) sshkey_free(k1); sshbuf_reset(fuzzed); } sshbuf_free(fuzzed); fuzz_cleanup(fuzz); TEST_DONE(); TEST_START("fuzz RSA private"); buf = load_file("rsa_1"); fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), sshbuf_len(buf)); ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", &k1, NULL), 0); sshkey_free(k1); sshbuf_free(buf); ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); TEST_ONERROR(onerror, fuzz); for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); ASSERT_INT_EQ(r, 0); if (sshkey_parse_private_fileblob(fuzzed, "", "key", &k1, NULL) == 0) sshkey_free(k1); sshbuf_reset(fuzzed); } sshbuf_free(fuzzed); fuzz_cleanup(fuzz); TEST_DONE(); TEST_START("fuzz RSA new-format private"); buf = load_file("rsa_n"); fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), sshbuf_len(buf)); ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", &k1, NULL), 0); sshkey_free(k1); sshbuf_free(buf); ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); TEST_ONERROR(onerror, fuzz); for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); ASSERT_INT_EQ(r, 0); if (sshkey_parse_private_fileblob(fuzzed, "", "key", &k1, NULL) == 0) sshkey_free(k1); sshbuf_reset(fuzzed); } sshbuf_free(fuzzed); fuzz_cleanup(fuzz); TEST_DONE(); TEST_START("fuzz DSA private"); buf = load_file("dsa_1"); fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), sshbuf_len(buf)); ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", &k1, NULL), 0); sshkey_free(k1); sshbuf_free(buf); ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); TEST_ONERROR(onerror, fuzz); for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); ASSERT_INT_EQ(r, 0); if (sshkey_parse_private_fileblob(fuzzed, "", "key", &k1, NULL) == 0) sshkey_free(k1); sshbuf_reset(fuzzed); } sshbuf_free(fuzzed); fuzz_cleanup(fuzz); TEST_DONE(); TEST_START("fuzz DSA new-format private"); buf = load_file("dsa_n"); fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), sshbuf_len(buf)); ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", &k1, NULL), 0); sshkey_free(k1); sshbuf_free(buf); ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); TEST_ONERROR(onerror, fuzz); for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); ASSERT_INT_EQ(r, 0); if (sshkey_parse_private_fileblob(fuzzed, "", "key", &k1, NULL) == 0) sshkey_free(k1); sshbuf_reset(fuzzed); } sshbuf_free(fuzzed); fuzz_cleanup(fuzz); TEST_DONE(); #ifdef OPENSSL_HAS_ECC TEST_START("fuzz ECDSA private"); buf = load_file("ecdsa_1"); fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), sshbuf_len(buf)); ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", &k1, NULL), 0); sshkey_free(k1); sshbuf_free(buf); ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); TEST_ONERROR(onerror, fuzz); for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); ASSERT_INT_EQ(r, 0); if (sshkey_parse_private_fileblob(fuzzed, "", "key", &k1, NULL) == 0) sshkey_free(k1); sshbuf_reset(fuzzed); } sshbuf_free(fuzzed); fuzz_cleanup(fuzz); TEST_DONE(); TEST_START("fuzz ECDSA new-format private"); buf = load_file("ecdsa_n"); fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), sshbuf_len(buf)); ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", &k1, NULL), 0); sshkey_free(k1); sshbuf_free(buf); ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); TEST_ONERROR(onerror, fuzz); for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); ASSERT_INT_EQ(r, 0); if (sshkey_parse_private_fileblob(fuzzed, "", "key", &k1, NULL) == 0) sshkey_free(k1); sshbuf_reset(fuzzed); } sshbuf_free(fuzzed); fuzz_cleanup(fuzz); TEST_DONE(); #endif TEST_START("fuzz Ed25519 private"); buf = load_file("ed25519_1"); fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), sshbuf_len(buf)); ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", &k1, NULL), 0); sshkey_free(k1); sshbuf_free(buf); ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); TEST_ONERROR(onerror, fuzz); for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); ASSERT_INT_EQ(r, 0); if (sshkey_parse_private_fileblob(fuzzed, "", "key", &k1, NULL) == 0) sshkey_free(k1); sshbuf_reset(fuzzed); } sshbuf_free(fuzzed); fuzz_cleanup(fuzz); TEST_DONE(); TEST_START("fuzz RSA public"); buf = load_file("rsa_1"); ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", &k1, NULL), 0); sshbuf_free(buf); public_fuzz(k1); sshkey_free(k1); TEST_DONE(); TEST_START("fuzz RSA cert"); ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1"), &k1), 0); public_fuzz(k1); sshkey_free(k1); TEST_DONE(); TEST_START("fuzz DSA public"); buf = load_file("dsa_1"); ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", &k1, NULL), 0); sshbuf_free(buf); public_fuzz(k1); sshkey_free(k1); TEST_DONE(); TEST_START("fuzz DSA cert"); ASSERT_INT_EQ(sshkey_load_cert(test_data_file("dsa_1"), &k1), 0); public_fuzz(k1); sshkey_free(k1); TEST_DONE(); #ifdef OPENSSL_HAS_ECC TEST_START("fuzz ECDSA public"); buf = load_file("ecdsa_1"); ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", &k1, NULL), 0); sshbuf_free(buf); public_fuzz(k1); sshkey_free(k1); TEST_DONE(); TEST_START("fuzz ECDSA cert"); ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ecdsa_1"), &k1), 0); public_fuzz(k1); sshkey_free(k1); TEST_DONE(); #endif TEST_START("fuzz Ed25519 public"); buf = load_file("ed25519_1"); ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", &k1, NULL), 0); sshbuf_free(buf); public_fuzz(k1); sshkey_free(k1); TEST_DONE(); TEST_START("fuzz Ed25519 cert"); ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ed25519_1"), &k1), 0); public_fuzz(k1); sshkey_free(k1); TEST_DONE(); TEST_START("fuzz RSA sig"); buf = load_file("rsa_1"); ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", &k1, NULL), 0); sshbuf_free(buf); sig_fuzz(k1); sshkey_free(k1); TEST_DONE(); TEST_START("fuzz DSA sig"); buf = load_file("dsa_1"); ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", &k1, NULL), 0); sshbuf_free(buf); sig_fuzz(k1); sshkey_free(k1); TEST_DONE(); #ifdef OPENSSL_HAS_ECC TEST_START("fuzz ECDSA sig"); buf = load_file("ecdsa_1"); ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", &k1, NULL), 0); sshbuf_free(buf); sig_fuzz(k1); sshkey_free(k1); TEST_DONE(); #endif TEST_START("fuzz Ed25519 sig"); buf = load_file("ed25519_1"); ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key", &k1, NULL), 0); sshbuf_free(buf); sig_fuzz(k1); sshkey_free(k1); TEST_DONE(); /* XXX fuzz decoded new-format blobs too */ }