static void recv_rexec_state(int fd, Buffer *conf) { Buffer m; char *cp; u_int len; debug3("%s: entering fd = %d", __func__, fd); buffer_init(&m); if (ssh_msg_recv(fd, &m) == -1) fatal("%s: ssh_msg_recv failed", __func__); if (buffer_get_char(&m) != 0) fatal("%s: rexec version mismatch", __func__); cp = buffer_get_string(&m, &len); if (conf != NULL) buffer_append(conf, cp, len + 1); xfree(cp); if (buffer_get_int(&m)) { if (sensitive_data.server_key != NULL) key_free(sensitive_data.server_key); sensitive_data.server_key = key_new_private(KEY_RSA1); buffer_get_bignum(&m, sensitive_data.server_key->rsa->e); buffer_get_bignum(&m, sensitive_data.server_key->rsa->n); buffer_get_bignum(&m, sensitive_data.server_key->rsa->d); buffer_get_bignum(&m, sensitive_data.server_key->rsa->iqmp); buffer_get_bignum(&m, sensitive_data.server_key->rsa->p); buffer_get_bignum(&m, sensitive_data.server_key->rsa->q); rsa_generate_additional_parameters( sensitive_data.server_key->rsa); } buffer_free(&m); debug3("%s: done", __func__); }
Key *key_private_deserialize(buffer_t *blob) { int success = 0; char *type_name = NULL; Key *k = NULL; unsigned int pklen, sklen; int type; type_name = buffer_get_string_msg(blob, NULL); if (type_name == NULL) goto error; type = get_keytype_from_name(type_name); k = key_new_private(type); switch (type) { case KEY_RSA: buffer_get_bignum2_msg(blob, k->rsa->n); buffer_get_bignum2_msg(blob, k->rsa->e); buffer_get_bignum2_msg(blob, k->rsa->d); buffer_get_bignum2_msg(blob, k->rsa->iqmp); buffer_get_bignum2_msg(blob, k->rsa->p); buffer_get_bignum2_msg(blob, k->rsa->q); /* Generate additional parameters */ rsa_generate_additional_parameters(k->rsa); break; case KEY_DSA: buffer_get_bignum2_msg(blob, k->dsa->p); buffer_get_bignum2_msg(blob, k->dsa->q); buffer_get_bignum2_msg(blob, k->dsa->g); buffer_get_bignum2_msg(blob, k->dsa->pub_key); buffer_get_bignum2_msg(blob, k->dsa->priv_key); break; case KEY_ECDSA256: case KEY_ECDSA384: case KEY_ECDSA521: { int success = 0; unsigned int nid; char *curve = NULL; ssh_keytype skt; BIGNUM *exponent = NULL; EC_POINT *q = NULL; nid = keytype_to_cipher_nid(type); curve = buffer_get_string_msg(blob, NULL); skt = key_curve_name_to_keytype(curve); if (nid != keytype_to_cipher_nid(skt)) goto ecdsa_error; k->ecdsa = EC_KEY_new_by_curve_name(nid); if (k->ecdsa == NULL) goto ecdsa_error; q = EC_POINT_new(EC_KEY_get0_group(k->ecdsa)); if (q == NULL) goto ecdsa_error; if ((exponent = BN_new()) == NULL) goto ecdsa_error; buffer_get_ecpoint_msg(blob, EC_KEY_get0_group(k->ecdsa), q); buffer_get_bignum2_msg(blob, exponent); if (EC_KEY_set_public_key(k->ecdsa, q) != 1) goto ecdsa_error; if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) goto ecdsa_error; if (key_ec_validate_public(EC_KEY_get0_group(k->ecdsa), EC_KEY_get0_public_key(k->ecdsa)) != 0) goto ecdsa_error; if (key_ec_validate_private(k->ecdsa) != 0) goto ecdsa_error; success = 1; ecdsa_error: free(curve); if (exponent) BN_clear_free(exponent); if (q) EC_POINT_free(q); if (success == 0) goto error; } break; case KEY_ED25519: k->ed25519_pk = buffer_get_string_msg(blob, &pklen); k->ed25519_sk = buffer_get_string_msg(blob, &sklen); if (pklen != ED25519_PK_SZ) goto error; if (sklen != ED25519_SK_SZ) goto error; break; default: goto error; break; } /* enable blinding */ switch (k->type) { case KEY_RSA1: case KEY_RSA: if (RSA_blinding_on(k->rsa, NULL) != 1) goto error; break; } success = 1; error: free(type_name); if (success == 0) { key_free(k); k = NULL; } return (k); }
static int sshkey_parse_private_rsa1(struct sshbuf *blob, const char *passphrase, struct sshkey **keyp, char **commentp) { int r; u_int16_t check1, check2; u_int8_t cipher_type; struct sshbuf *decrypted = NULL, *copy = NULL; u_char *cp; char *comment = NULL; struct sshcipher_ctx ciphercontext; const struct sshcipher *cipher; struct sshkey *prv = NULL; *keyp = NULL; if (commentp != NULL) *commentp = NULL; /* Check that it is at least big enough to contain the ID string. */ if (sshbuf_len(blob) < sizeof(authfile_id_string)) return SSH_ERR_INVALID_FORMAT; /* * Make sure it begins with the id string. Consume the id string * from the buffer. */ if (memcmp(sshbuf_ptr(blob), authfile_id_string, sizeof(authfile_id_string)) != 0) return SSH_ERR_INVALID_FORMAT; if ((prv = sshkey_new_private(KEY_RSA1)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((copy = sshbuf_fromb(blob)) == NULL || (decrypted = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshbuf_consume(copy, sizeof(authfile_id_string))) != 0) goto out; /* Read cipher type. */ if ((r = sshbuf_get_u8(copy, &cipher_type)) != 0 || (r = sshbuf_get_u32(copy, NULL)) != 0) /* reserved */ goto out; /* Read the public key and comment from the buffer. */ if ((r = sshbuf_get_u32(copy, NULL)) != 0 || /* key bits */ (r = sshbuf_get_bignum1(copy, prv->rsa->n)) != 0 || (r = sshbuf_get_bignum1(copy, prv->rsa->e)) != 0 || (r = sshbuf_get_cstring(copy, &comment, NULL)) != 0) goto out; /* Check that it is a supported cipher. */ cipher = cipher_by_number(cipher_type); if (cipher == NULL) { r = SSH_ERR_KEY_UNKNOWN_CIPHER; goto out; } /* Initialize space for decrypted data. */ if ((r = sshbuf_reserve(decrypted, sshbuf_len(copy), &cp)) != 0) goto out; /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ if ((r = cipher_set_key_string(&ciphercontext, cipher, passphrase, CIPHER_DECRYPT)) != 0) goto out; if ((r = cipher_crypt(&ciphercontext, cp, sshbuf_ptr(copy), sshbuf_len(copy), 0, 0)) != 0) { cipher_cleanup(&ciphercontext); goto out; } if ((r = cipher_cleanup(&ciphercontext)) != 0) goto out; if ((r = sshbuf_get_u16(decrypted, &check1)) != 0 || (r = sshbuf_get_u16(decrypted, &check2)) != 0) goto out; if (check1 != check2) { r = SSH_ERR_KEY_WRONG_PASSPHRASE; goto out; } /* Read the rest of the private key. */ if ((r = sshbuf_get_bignum1(decrypted, prv->rsa->d)) != 0 || (r = sshbuf_get_bignum1(decrypted, prv->rsa->iqmp)) != 0 || (r = sshbuf_get_bignum1(decrypted, prv->rsa->q)) != 0 || (r = sshbuf_get_bignum1(decrypted, prv->rsa->p)) != 0) goto out; /* calculate p-1 and q-1 */ if ((r = rsa_generate_additional_parameters(prv->rsa)) != 0) goto out; /* enable blinding */ if (RSA_blinding_on(prv->rsa, NULL) != 1) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } r = 0; *keyp = prv; prv = NULL; if (commentp != NULL) { *commentp = comment; comment = NULL; } out: bzero(&ciphercontext, sizeof(ciphercontext)); if (comment != NULL) free(comment); if (prv != NULL) sshkey_free(prv); if (copy != NULL) sshbuf_free(copy); if (decrypted != NULL) sshbuf_free(decrypted); return r; }
static Key * key_load_private_rsa1(int fd, const char *filename, const char *passphrase, char **commentp) { int i, check1, check2, cipher_type; off_t len; Buffer buffer, decrypted; u_char *cp; CipherContext ciphercontext; Cipher *cipher; Key *prv = NULL; struct stat st; if (fstat(fd, &st) < 0) { error("fstat for key file %.200s failed: %.100s", filename, strerror(errno)); close(fd); return NULL; } len = st.st_size; buffer_init(&buffer); cp = buffer_append_space(&buffer, len); if (read(fd, cp, (size_t) len) != (size_t) len) { debug("Read from key file %.200s failed: %.100s", filename, strerror(errno)); buffer_free(&buffer); close(fd); return NULL; } /* Check that it is at least big enough to contain the ID string. */ if (len < sizeof(authfile_id_string)) { debug3("Not a RSA1 key file %.200s.", filename); buffer_free(&buffer); close(fd); return NULL; } /* * Make sure it begins with the id string. Consume the id string * from the buffer. */ for (i = 0; i < sizeof(authfile_id_string); i++) if (buffer_get_char(&buffer) != authfile_id_string[i]) { debug3("Not a RSA1 key file %.200s.", filename); buffer_free(&buffer); close(fd); return NULL; } /* Read cipher type. */ cipher_type = buffer_get_char(&buffer); (void) buffer_get_int(&buffer); /* Reserved data. */ /* Read the public key from the buffer. */ (void) buffer_get_int(&buffer); prv = key_new_private(KEY_RSA1); buffer_get_bignum(&buffer, prv->rsa->n); buffer_get_bignum(&buffer, prv->rsa->e); if (commentp) *commentp = buffer_get_string(&buffer, NULL); else xfree(buffer_get_string(&buffer, NULL)); /* Check that it is a supported cipher. */ cipher = cipher_by_number(cipher_type); if (cipher == NULL) { debug("Unsupported cipher %d used in key file %.200s.", cipher_type, filename); buffer_free(&buffer); goto fail; } /* Initialize space for decrypted data. */ buffer_init(&decrypted); cp = buffer_append_space(&decrypted, buffer_len(&buffer)); /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ cipher_set_key_string(&ciphercontext, cipher, passphrase, CIPHER_DECRYPT); cipher_crypt(&ciphercontext, cp, buffer_ptr(&buffer), buffer_len(&buffer)); cipher_cleanup(&ciphercontext); memset(&ciphercontext, 0, sizeof(ciphercontext)); buffer_free(&buffer); check1 = buffer_get_char(&decrypted); check2 = buffer_get_char(&decrypted); if (check1 != buffer_get_char(&decrypted) || check2 != buffer_get_char(&decrypted)) { if (strcmp(passphrase, "") != 0) debug("Bad passphrase supplied for key file %.200s.", filename); /* Bad passphrase. */ buffer_free(&decrypted); goto fail; } /* Read the rest of the private key. */ buffer_get_bignum(&decrypted, prv->rsa->d); buffer_get_bignum(&decrypted, prv->rsa->iqmp); /* u */ /* in SSL and SSH v1 p and q are exchanged */ buffer_get_bignum(&decrypted, prv->rsa->q); /* p */ buffer_get_bignum(&decrypted, prv->rsa->p); /* q */ /* calculate p-1 and q-1 */ rsa_generate_additional_parameters(prv->rsa); buffer_free(&decrypted); /* enable blinding */ if (RSA_blinding_on(prv->rsa, NULL) != 1) { error("key_load_private_rsa1: RSA_blinding_on failed"); goto fail; } close(fd); return prv; fail: if (commentp) xfree(*commentp); close(fd); key_free(prv); return NULL; }