### Encrypt Data Example (C) Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/cipher.md An example demonstrating how to encrypt data using OpenSSH cipher functions. It includes selecting a cipher, verifying key and IV lengths, initializing the cipher context, performing encryption, and cleaning up resources. ```c #include "cipher.h" #include "ssherr.h" int encrypt_data(const char *cipher_name, const u_char *key, size_t keylen, const u_char *iv, size_t ivlen, u_char *plaintext, size_t plen) { const struct sshcipher *cipher; struct sshcipher_ctx *ctx = NULL; int ret; // Select cipher cipher = cipher_by_name(cipher_name); if (cipher == NULL) { return SSH_ERR_NO_CIPHER_ALG_MATCH; } // Verify key and IV lengths if (cipher_keylen(cipher) != keylen || cipher_ivlen(cipher) != ivlen) { return SSH_ERR_INVALID_ARGUMENT; } // Initialize cipher for encryption ret = cipher_init(&ctx, cipher, key, keylen, iv, ivlen, 1); if (ret != SSH_ERR_SUCCESS) { return ret; } // Encrypt data ret = cipher_crypt(ctx, 0, plaintext, plaintext, plen, 0, 0); if (ret != SSH_ERR_SUCCESS) { cipher_free(ctx); return ret; } // Clean up cipher_free(ctx); return SSH_ERR_SUCCESS; } ``` -------------------------------- ### Get Compression Algorithm List (C) Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/cipher.md Generates a static string containing a list of available compression algorithms. Pass a non-zero value for internal_only to get a list restricted to internal use. ```c const char *compression_alg_list(int internal_only) ``` ```c const char *list = compression_alg_list(0); printf("Compression: %s\n", list); ``` -------------------------------- ### Manage SSH Keys Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/README.md Provides examples for creating, freeing, generating, signing, and verifying SSH keys. Supports various key types like ED25519. ```c sshkey_new(KEY_ED25519); sshkey_free(key); sshkey_generate(KEY_ED25519, 0, &key); sshkey_sign(key, &sig, &sig_len, data, data_len, NULL, NULL, NULL, 0); sshkey_verify(pubkey, sig, sig_len, data, data_len, NULL, 0, NULL); ``` -------------------------------- ### WebAuthn Enrollment Start Source: https://github.com/openssh/openssh-portable/blob/master/regress/unittests/sshsig/webauthn.html Initiates the WebAuthn enrollment process by generating a challenge and user ID, then calling `navigator.credentials.create` with public key options. This function sets up the necessary parameters for credential creation. ```javascript function enrollStart(username) { let challenge = new Uint8Array(32) window.crypto.getRandomValues(challenge) let userid = new Uint8Array(8) window.crypto.getRandomValues(userid) console.log("challenge:" + btoa(challenge)) console.log("userid:" + btoa(userid)) let pkopts = { challenge: challenge, rp: { name: window.location.host, id: window.location.host, }, user: { id: userid, name: username, displayName: username, }, authenticatorSelection: { authenticatorAttachment: "cross-platform", userVerification: "discouraged", }, pubKeyCredParams: [{alg: -7, type: "public-key"}], // ES256 timeout: 30 * 1000, }; console.dir(pkopts) window.enrollOpts = pkopts let credpromise = navigator.credentials.create({ publicKey: pkopts }); credpromise.then(enrollSuccess, enrollFailure) } ``` -------------------------------- ### Linking OpenSSH and OpenSSL with GCC Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/README.md This command demonstrates how to compile a C program and link it against the OpenSSH and OpenSSL libraries using GCC. Ensure to replace placeholder paths with your actual installation locations. ```bash gcc -o program program.c \ -I/path/to/openssh-portable \ -L/path/to/built/objects \ -lssh -lcrypto ``` -------------------------------- ### Get Output Buffer Pointer and Length Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/ssh-api.md Retrieve a pointer to the current output data and its length using ssh_output_ptr. This data should be sent over the network. ```c const u_char *ssh_output_ptr(struct ssh *ssh, size_t *len) ``` ```c size_t output_len; const u_char *output_data = ssh_output_ptr(ssh, &output_len); if (output_data != NULL) { ssize_t sent = send(socket_fd, output_data, output_len, 0); if (sent > 0) { ssh_output_consume(ssh, sent); } } ``` -------------------------------- ### Get Application Data Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/ssh-api.md Retrieves application-specific data previously attached to an SSH connection. Returns NULL if no data has been set. ```c void *ssh_get_app_data(struct ssh *ssh) ``` ```c struct my_context *ctx = ssh_get_app_data(ssh); if (ctx != NULL) { // use ctx } ``` -------------------------------- ### Handle SSH Errors Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/README.md Provides an example of checking return codes for SSH operations and printing error messages to standard error using `ssh_err`. ```c if (ret != SSH_ERR_SUCCESS) { fprintf(stderr, "%s\n", ssh_err(ret)); } ``` -------------------------------- ### API Reference Structure Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/COMPLETION_SUMMARY.txt The API reference is organized into modules, each detailing functions, parameters, return values, error conditions, and usage examples. ```APIDOC ## api-reference/ Each module includes: - Function signature with exact types - Parameter table (name | type | required | default | description) - Return value documentation - Error conditions (Throws/Rejects) - Usage examples (30-50 lines each) - Source file references with line numbers - Links to related modules ``` -------------------------------- ### OpenSSH Error Message Examples Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/README.md Illustrates common error messages returned by OpenSSH functions. Check ssh_err() return codes for detailed error information. ```c ret = sshkey_generate(KEY_RSA, 512, &key); // ssh_err(ret) → "RSA keys require at least 1024 bits" ``` ```c ret = cipher_init(&ctx, cipher, key, 8, iv, 16, 1); // ssh_err(ret) → "Key length mismatch" ``` ```c ret = sshkey_verify(pubkey, sig, sig_len, data, data_len, NULL, 0, NULL); if (ret == SSH_ERR_SIGNATURE_INVALID) { // Signature doesn't match; either corrupted or forged } ``` -------------------------------- ### Get SSH Buffer Available Space - C Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/sshbuf.md Use sshbuf_avail to determine the remaining space in an SSH buffer before it reaches its maximum configured size. This is important for preventing buffer overflows. ```c struct sshbuf *buf = sshbuf_new(); sshbuf_set_max_size(buf, 1024); sshbuf_put_u32(buf, 42); printf("Available: %zu\n", sshbuf_avail(buf)); // Prints: 1020 sshbuf_free(buf); ``` -------------------------------- ### Initialize and Crypt with Ciphers Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/README.md Shows how to initialize a cipher context by name, set up encryption/decryption parameters, perform cryptographic operations, and free the context. ```c cipher_by_name("aes128-ctr"); cipher_init(&ctx, cipher, key, keylen, iv, ivlen, 1); cipher_crypt(ctx, 0, dst, src, len, 0, 0); cipher_free(ctx); ``` -------------------------------- ### Get SSH Cipher by Name Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/cipher.md Retrieves a cipher structure based on its algorithm name. Returns NULL if the cipher is not found or not compiled. Use this to get cipher details like key length. ```c const struct sshcipher *cipher_by_name(const char *name) ``` ```c const struct sshcipher *cipher = cipher_by_name("aes128-ctr"); if (cipher == NULL) { fprintf(stderr, "Cipher not available\n"); return SSH_ERR_NO_CIPHER_ALG_MATCH; } u_int keylen = cipher_keylen(cipher); printf("AES-128-CTR key length: %u bytes\n", keylen); ``` -------------------------------- ### Get Mutable SSH Buffer Pointer - C Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/sshbuf.md Use sshbuf_mutable_ptr to get a pointer to the data within an SSH buffer that can be modified. This function is only applicable to writable buffers and returns NULL if the buffer is read-only or empty. ```c struct sshbuf *buf = sshbuf_new(); u_char *ptr = sshbuf_mutable_ptr(buf); if (ptr != NULL) { memcpy(ptr, some_data, some_len); } sshbuf_free(buf); ``` -------------------------------- ### Initialize Application Source: https://github.com/openssh/openssh-portable/blob/master/regress/unittests/sshsig/webauthn.html Sets up event listeners and performs security checks for the page environment. ```javascript function init() { if (document.location.protocol != "https:") { error("This page must be loaded via https") const assertsubmit = document.getElementById('assertsubmit') assertsubmit.disabled = true } const enrollform = document.getElementById('enrollform'); enrollform.addEventListener('submit', enrollform_submit); const assertform = document.getElementById('assertform'); assertform.addEventListener('submit', assertform_submit); const assertsigtype = document.getElementById('message_sshsig'); assertsigtype.onclick = toggleNamespaceVisibility; } ``` -------------------------------- ### Initialize and Free SSH Connection Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/README.md Demonstrates the basic initialization and cleanup of an SSH connection context. Use `ssh_init` to set up the context and `ssh_free` to release resources. ```c ssh_init(&ssh, is_server, NULL); ssh_free(ssh); ``` -------------------------------- ### Typical SSH Client Session Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/README.md Illustrates the steps for establishing an SSH connection, including agent interaction, key exchange, authentication, and channel management. Ensure proper error handling for network operations. ```c // Connect to agent for keys ssh_get_authentication_socket(&agent_fd); ssh_fetch_identitylist(agent_fd, &idl); // Initialize SSH connection ssh_init(&ssh, 0, NULL); ssh_add_hostkey(ssh, server_hostkey); // Process packets until authenticated while (!authenticated) { ret = ssh_packet_next(ssh, &packet_type); if (ret == SSH_ERR_MESSAGE_INCOMPLETE) { // Need more data bytes_read = recv(socket_fd, buf, sizeof(buf), 0); ssh_input_append(ssh, buf, bytes_read); } // Handle packet... } // Clean up ssh_close_authentication_socket(agent_fd); ssh_free_identitylist(idl); ssh_free(ssh); ``` -------------------------------- ### Get SSH Key Type Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/sshkey.md Retrieves the string name representing the type of an SSH key (e.g., "ssh-ed25519"). ```c printf("Key type: %s\n", sshkey_type(key)); ``` -------------------------------- ### Constants and Configuration Structure Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/COMPLETION_SUMMARY.txt The configuration.md file lists and explains all constants, configuration options, and environment variables. ```APIDOC ## configuration.md - Build configuration options - Runtime constants - Protocol parameters - Algorithm names - Environment variables - Code usage examples ``` -------------------------------- ### Get Cipher Security Material Length Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/cipher.md Retrieves the length of security-sensitive material (key + IV) that needs to be securely cleared by the cipher. ```c u_int cipher_seclen(const struct sshcipher *cipher) ``` -------------------------------- ### Get Cipher IV Length Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/cipher.md Retrieves the initialization vector (IV) length in bytes required for a cipher. Allocate a buffer of this size for the IV. ```c u_int cipher_ivlen(const struct sshcipher *cipher) ``` ```c u_int ivlen = cipher_ivlen(cipher); u_char iv[ivlen]; // Generate random IV ``` -------------------------------- ### Using SSH Constants for Buffer Size and Certificate Limits Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/configuration.md Demonstrates the use of SSH constants like SSHBUF_SIZE_MAX and SSHKEY_CERT_MAX_PRINCIPALS for setting buffer limits and checking certificate principals. Ensure necessary headers are included. ```c #include "ssh.h" #include "sshkey.h" #include "sshbuf.h" int setup_ssh_connection() { struct ssh *ssh = NULL; struct sshkey *hostkey = NULL; struct sshbuf *buf = NULL; // Allocate buffer with safety limit buf = sshbuf_new(); if (sshbuf_set_max_size(buf, SSHBUF_SIZE_MAX) != 0) { fprintf(stderr, "Failed to set buffer limit\n"); return -1; } // Initialize SSH connection if (ssh_init(&ssh, 0, NULL) != 0) { fprintf(stderr, "SSH initialization failed\n"); goto cleanup; } // Check certificate principal limit if (some_cert->nprincipals > SSHKEY_CERT_MAX_PRINCIPALS) { fprintf(stderr, "Too many principals in certificate\n"); goto cleanup; } cleanup: if (buf) sshbuf_free(buf); if (ssh) ssh_free(ssh); if (hostkey) sshkey_free(hostkey); return 0; } ``` -------------------------------- ### Get Cipher Key Length Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/cipher.md Retrieves the required key length in bytes for a given cipher. Use this to allocate buffers for cryptographic keys. ```c u_int cipher_keylen(const struct sshcipher *cipher) ``` ```c const struct sshcipher *cipher = cipher_by_name("aes256-ctr"); u_int keylen = cipher_keylen(cipher); printf("Key size: %u bytes\n", keylen); // Prints: 32 bytes ``` -------------------------------- ### Build OpenSSH from Release Tarball Source: https://github.com/openssh/openssh-portable/blob/master/README.md Standard procedure for building OpenSSH from a release tarball. Requires autoconf and make. Configure options can customize the build. ```bash tar zxvf openssh-X.YpZ.tar.gz cd openssh ./configure # [options] make && make tests ``` -------------------------------- ### Common SSH Buffer Usage Pattern Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/sshbuf.md Demonstrates the typical workflow for creating an SSH buffer, writing data to it, sending it over a network socket, and cleaning up resources. Ensure proper error handling after each operation. ```c struct sshbuf *buf = sshbuf_new(); if (buf == NULL) { return SSH_ERR_ALLOC_FAIL; } // Write data int ret = sshbuf_put_u32(buf, 42); if (ret != SSH_ERR_SUCCESS) goto cleanup; ret = sshbuf_put_string(buf, data, data_len); if (ret != SSH_ERR_SUCCESS) goto cleanup; // Send over network const u_char *ptr = sshbuf_ptr(buf); size_t len = sshbuf_len(buf); if (send(fd, ptr, len, 0) < 0) goto cleanup; cleanup: sshbuf_free(buf); return ret; ``` -------------------------------- ### Load and Validate Private Key Sequence Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/errors.md Demonstrates the typical sequence for loading a private key file, including handling specific errors like incorrect passphrase or unsupported cipher. Returns the error code if loading fails. ```c // Typical sequence for loading and validating a private key struct sshkey *key = NULL; char *comment = NULL; int ret; ret = sshkey_parse_private_fileblob(filebuf, passphrase, &key, &comment); if (ret == SSH_ERR_KEY_WRONG_PASSPHRASE) { // Prompt user to retry with correct passphrase } else if (ret == SSH_ERR_KEY_UNKNOWN_CIPHER) { // Key file format not supported } else if (ret != SSH_ERR_SUCCESS) { fprintf(stderr, "Failed to load key: %s\n", ssh_err(ret)); return ret; } // Key loaded successfully printf("Key: %s (%s)\n", comment, sshkey_type(key)); ``` -------------------------------- ### Get Cipher Block Size Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/cipher.md Retrieves the block size in bytes for a cipher. This is typically 8 or 16 bytes for block ciphers, or 0 for stream ciphers. ```c u_int cipher_blocksize(const struct sshcipher *cipher) ``` ```c u_int blocksize = cipher_blocksize(cipher); printf("Block size: %u\n", blocksize); ``` -------------------------------- ### SSH Key Management Operations Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/README.md Demonstrates generating, deriving public keys, signing data, and verifying signatures using SSH keys. Remember to free allocated memory for keys and signatures. ```c // Generate a new key struct sshkey *key = NULL; sshkey_generate(KEY_ED25519, 0, &key); // Get public key struct sshkey *pubkey = NULL; sshkey_from_private(key, &pubkey); // Sign data u_char *sig = NULL; size_t sig_len = 0; sshkey_sign(key, &sig, &sig_len, data, data_len, NULL, NULL, NULL, 0); // Verify signature int valid = sshkey_verify(pubkey, sig, sig_len, data, data_len, NULL, 0, NULL); // Cleanup free(sig); sshkey_free(pubkey); sshkey_free(key); ``` -------------------------------- ### Build OpenSSH from Git Repository Source: https://github.com/openssh/openssh-portable/blob/master/README.md Steps to build OpenSSH directly from its git master branch. Requires autoconf to generate the configure script. Includes checking out the repository, running autoreconf, configuring, and building. ```bash git clone https://github.com/openssh/openssh-portable # or https://anongit.mindrot.org/openssh.git cd openssh-portable autoreconf ./configure make && make tests ``` -------------------------------- ### Get SSH Agent Socket Path Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/configuration.md Retrieves the path to the SSH agent's authentication socket from the environment. Logs an error if the SSH_AUTH_SOCK environment variable is not set. ```c const char *agent_socket = getenv(SSH_AUTHSOCKET_ENV_NAME); if (agent_socket == NULL) { fprintf(stderr, "SSH_AUTH_SOCK not set\n"); } ``` -------------------------------- ### Get SSH Buffer Maximum Size Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/sshbuf.md Retrieves the current maximum size limit configured for an SSH buffer. This is useful for understanding buffer constraints before performing operations. ```c size_t sshbuf_max_size(const struct sshbuf *buf) ``` -------------------------------- ### Initialize SSH Connection Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/ssh-api.md Initializes a new SSH connection object. Use this before other SSH operations. Pass 0 for `is_server` for client mode and non-zero for server mode. Optional `kex_params` can be provided, otherwise defaults are used. ```c int ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) ``` ```c struct ssh *ssh; struct kex_params kex_params = {0}; int ret = ssh_init(&ssh, 0, &kex_params); if (ret != SSH_ERR_SUCCESS) { fprintf(stderr, "Failed to initialize SSH: %s\n", ssh_err(ret)); return ret; } ``` -------------------------------- ### cipher_init Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/cipher.md Initializes a cipher context for either encryption or decryption using the provided cipher, key, IV, and mode. ```APIDOC ## cipher_init ### Description Initialize a cipher context for encryption or decryption. ### Signature ```c int cipher_init(struct sshcipher_ctx **ctxp, const struct sshcipher *cipher, const u_char *key, u_int keylen, const u_char *iv, u_int ivlen, int do_encrypt) ``` ### Parameters #### Path Parameters - **ctxp** (struct sshcipher_ctx **) - Required - Pointer to store allocated cipher context - **cipher** (const struct sshcipher *) - Required - Cipher from cipher_by_name() - **key** (const u_char *) - Required - Encryption/decryption key material - **keylen** (u_int) - Required - Key length in bytes - **iv** (const u_char *) - Required - Initialization vector - **ivlen** (u_int) - Required - IV length in bytes - **do_encrypt** (int) - Required - Non-zero for encryption, zero for decryption ### Returns Zero on success, negative SSH_ERR_* error code on failure. ### Throws/Rejects - SSH_ERR_INVALID_ARGUMENT: Key or IV length is incorrect - SSH_ERR_LIBCRYPTO_ERROR: OpenSSL operation failed - SSH_ERR_ALLOC_FAIL: Memory allocation failed ### Requirements - Key length must match cipher_keylen(cipher) - IV length must match cipher_ivlen(cipher) ### Example ```c struct sshcipher_ctx *ctx = NULL; const struct sshcipher *cipher = cipher_by_name("aes128-ctr"); if (cipher == NULL) return SSH_ERR_NO_CIPHER_ALG_MATCH; u_int keylen = cipher_keylen(cipher); u_int ivlen = cipher_ivlen(cipher); u_char key[16]; // 128 bits u_char iv[16]; // IV size matches cipher block size // Fill key and iv from key derivation int ret = cipher_init(&ctx, cipher, key, keylen, iv, ivlen, 1); if (ret != SSH_ERR_SUCCESS) { fprintf(stderr, "Cipher init failed: %s\n", ssh_err(ret)); return ret; } // Use ctx for encryption cipher_free(ctx); ``` ``` -------------------------------- ### Get Cipher Authentication Tag Length Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/cipher.md Retrieves the authentication tag length in bytes for AEAD (Authenticated Encryption with Associated Data) ciphers. Returns 0 for non-AEAD ciphers. ```c u_int cipher_authlen(const struct sshcipher *cipher) ``` ```c u_int authlen = cipher_authlen(cipher); if (authlen > 0) { printf("AEAD cipher with %u-byte tag\n", authlen); } ``` -------------------------------- ### Allocate and Initialize New SSH Key Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/sshkey.md Use `sshkey_new` to create a new key object of a specified type. Check for NULL return to handle allocation failures. ```c struct sshkey *key = sshkey_new(KEY_ED25519); if (key == NULL) { fprintf(stderr, "Failed to allocate key\n"); return SSH_ERR_ALLOC_FAIL; } ``` -------------------------------- ### Get SSH Buffer Length - C Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/sshbuf.md Use sshbuf_len to retrieve the current number of bytes stored within an SSH buffer. This function is helpful for monitoring buffer usage. ```c struct sshbuf *buf = sshbuf_new(); sshbuf_put_u32(buf, 42); printf("Buffer length: %zu\n", sshbuf_len(buf)); // Prints: 4 sshbuf_free(buf); ``` -------------------------------- ### Define kex_params Structure for SSH Key Exchange Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/ssh-api.md Defines the structure to hold key exchange parameters for `ssh_init()`. Pass NULL for default proposals or specify algorithm names. ```c struct kex_params { char *proposal[PROPOSAL_MAX]; }; ``` -------------------------------- ### Trigger Unknown Key Type Error Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/errors.md Shows how SSH_ERR_KEY_TYPE_UNKNOWN can be triggered by providing an invalid enum value to sshkey_new. This example highlights the importance of valid key type enumeration. ```c // SSH_ERR_KEY_TYPE_UNKNOWN when type enum is invalid struct sshkey *key = sshkey_new(999); // Returns NULL (alloc fails) ``` -------------------------------- ### Key Exchange Algorithm Proposal Indices (enum kex_init_proposals) Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/types.md Provides indices for key exchange algorithm proposals. These are used to access specific algorithm types within the kex_params.proposal[] array, covering key exchange, host keys, encryption, MAC, and compression algorithms. ```c enum kex_init_proposals { PROPOSAL_KEX_ALGS, PROPOSAL_SERVER_HOST_KEY_ALGS, PROPOSAL_ENC_ALGS_CTOS, PROPOSAL_ENC_ALGS_STOC, PROPOSAL_MAC_ALGS_CTOS, PROPOSAL_MAC_ALGS_STOC, PROPOSAL_COMP_ALGS_CTOS, PROPOSAL_COMP_ALGS_STOC, PROPOSAL_LANG_CTOS, PROPOSAL_LANG_STOC, PROPOSAL_MAX }; ``` -------------------------------- ### Get Cipher Context Key and IV Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/cipher.md Retrieve the current encryption key and initialization vector (IV) from a cipher context. This is typically used internally for operations like key re-keying. ```c int cipher_get_keyiv(struct sshcipher_ctx *ctx, u_char *buf, size_t len) ``` -------------------------------- ### Initiate WebAuthn Assertion Source: https://github.com/openssh/openssh-portable/blob/master/regress/unittests/sshsig/webauthn.html Initiates the WebAuthn assertion process using navigator.credentials.get with specified options, including challenge, RP ID, and allowed credentials. Logs success or failure. ```javascript function assertStart(message) { let assertReqOpts = { challenge: message, rpId: window.location.host, allowCredentials: [{ type: 'public-key', id: window.enrollResult.rawId, }], userVerification: "discouraged", timeout: (30 * 1000), } console.log("assertReqOpts") console.dir(assertReqOpts) window.assertReqOpts = assertReqOpts let assertpromise = navigator.credentials.get({ publicKey: assertReqOpts }); assertpromise.then(assertSuccess, assertFailure) } ``` -------------------------------- ### Create New SSH Buffer Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/sshbuf.md Use `sshbuf_new` to create an empty buffer. Check the return value for allocation failures. ```c struct sshbuf *buf = sshbuf_new(); if (buf == NULL) { fprintf(stderr, "Buffer allocation failed\n"); return SSH_ERR_ALLOC_FAIL; } // Use buffer sshbuf_free(buf); ``` -------------------------------- ### Get Cipher Warning Message (C) Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/cipher.md Retrieves a warning message if a cipher has security concerns. Returns NULL if no warnings are present. Use this to inform users about potential weaknesses in selected ciphers. ```c const char *cipher_warning_message(const struct sshcipher_ctx *ctx) ``` ```c const char *warning = cipher_warning_message(ctx); if (warning != NULL) { fprintf(stderr, "Warning: %s\n", warning); } ``` -------------------------------- ### ssh_init Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/ssh-api.md Initializes a new SSH connection object. This function sets up the necessary structures for an SSH connection, allowing for either client or server roles, and can be configured with specific key exchange parameters. ```APIDOC ## ssh_init ### Description Initialize a new SSH connection object with optional key exchange parameters. ### Signature ```c int ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) ``` ### Parameters #### Path Parameters - **sshp** (struct ssh **) - Required - Pointer to store allocated SSH connection object - **is_server** (int) - Required - Non-zero if this connection represents a server, zero for client - **kex_params** (struct kex_params *) - Optional - Optional key exchange parameters; if NULL, defaults are used ### Returns Zero on success, negative SSH_ERR_* error code on failure. ### Throws/Rejects - SSH_ERR_ALLOC_FAIL: Memory allocation failed ### Example ```c struct ssh *ssh; struct kex_params kex_params = {0}; int ret = ssh_init(&ssh, 0, &kex_params); if (ret != SSH_ERR_SUCCESS) { fprintf(stderr, "Failed to initialize SSH: %s\n", ssh_err(ret)); return ret; } ``` ``` -------------------------------- ### OpenSSH Portable Include Files Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/README.md These are the main header files required for using the OpenSSH API, key management, buffer operations, encryption, error handling, and agent communication. ```c #include "ssh_api.h" /* Main SSH API */ #include "sshkey.h" /* Key management */ #include "sshbuf.h" /* Buffer operations */ #include "cipher.h" /* Encryption */ #include "ssherr.h" /* Error codes */ #include "authfd.h" /* Agent communication */ ``` -------------------------------- ### Sign Data with SSH Agent Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/authfd.md Connects to the SSH agent, fetches available identities, and signs provided data using the first available key. Ensure the SSH agent is running and accessible. ```c #include "authfd.h" #include "sshkey.h" #include "ssherr.h" int sign_with_agent(const u_char *data, size_t data_len, u_char **sig_out, size_t *sig_len_out) { int agent_fd; struct ssh_identitylist *idl = NULL; u_char *signature = NULL; size_t sig_len = 0; int ret; // Connect to agent ret = ssh_get_authentication_socket(&agent_fd); if (ret != SSH_ERR_SUCCESS) { return ret; } // Get available keys ret = ssh_fetch_identitylist(agent_fd, &idl); if (ret != SSH_ERR_SUCCESS || idl == NULL) { ssh_close_authentication_socket(agent_fd); return ret; } // Sign with first key if (idl->nkeys > 0) { ret = ssh_agent_sign(agent_fd, idl->keys[0], &signature, &sig_len, data, data_len, NULL, 0); if (ret == SSH_ERR_SUCCESS) { *sig_out = signature; *sig_len_out = sig_len; } } // Cleanup ssh_free_identitylist(idl); ssh_close_authentication_socket(agent_fd); return ret; } ``` -------------------------------- ### Get Last Libcrypto Error Message Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/errors.md Call `ssherr_libcrypto` after encountering `SSH_ERR_LIBCRYPTO_ERROR` to retrieve the specific error message from the underlying OpenSSL library. Returns 'no openssl error' if no OpenSSL error is pending. ```c const char *ssherr_libcrypto(void) ``` ```c int ret = sshkey_sign(key, &sig, &sig_len, data, data_len, NULL, NULL, NULL, 0); if (ret == SSH_ERR_LIBCRYPTO_ERROR) { fprintf(stderr, "Crypto error: %s\n", ssherr_libcrypto()); } ``` -------------------------------- ### Get Read-Only SSH Buffer Pointer - C Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/sshbuf.md Use sshbuf_ptr to obtain a constant pointer to the data within an SSH buffer. This allows reading the buffer's contents without the risk of modification. Returns NULL if the buffer is empty. ```c struct sshbuf *buf = sshbuf_new(); sshbuf_put_u32(buf, 0x01020304); const u_char *data = sshbuf_ptr(buf); if (data != NULL) { printf("First byte: 0x%02x\n", data[0]); } sshbuf_free(buf); ``` -------------------------------- ### Toggle Namespace Visibility Source: https://github.com/openssh/openssh-portable/blob/master/regress/unittests/sshsig/webauthn.html Updates the UI state for the signature namespace input based on the selected signature type. ```javascript function toggleNamespaceVisibility() { const assertsigtype = document.getElementById('message_sshsig'); const assertsignamespace = document.getElementById('message_namespace'); assertsignamespace.disabled = !assertsigtype.checked; } ``` -------------------------------- ### sshbuf_new Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/sshbuf.md Creates a new, empty sshbuf buffer. Returns NULL on allocation failure. ```APIDOC ## sshbuf_new ### Description Create a new, empty sshbuf buffer. ### Returns Pointer to new buffer, or NULL on allocation failure. ### Example ```c struct sshbuf *buf = sshbuf_new(); if (buf == NULL) { fprintf(stderr, "Buffer allocation failed\n"); return SSH_ERR_ALLOC_FAIL; } // Use buffer sshbuf_free(buf); ``` ``` -------------------------------- ### Interact with SSH Agent Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/README.md Demonstrates functions for communicating with the SSH agent, including fetching the authentication socket, listing identities, signing data, and closing the connection. ```c ssh_get_authentication_socket(&fd); ssh_fetch_identitylist(fd, &idl); ssh_agent_sign(fd, key, &sig, &sig_len, data, data_len, NULL, 0); ssh_free_identitylist(idl); ssh_close_authentication_socket(fd); ``` -------------------------------- ### Add Security Key to Agent Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/authfd.md Demonstrates how to add a security key to the SSH agent using ssh_update_card. Ensure the agent socket is valid and provide necessary parameters like reader ID and confirmation. ```c int ret = ssh_update_card(agent_fd, 1, // Add card "reader-name", // Device ID "1234", // PIN 0, // No timeout 1, // Require confirmation NULL, 0, // No constraints 0, NULL, 0); // No certificates if (ret != SSH_ERR_SUCCESS) { fprintf(stderr, "Failed to add security key: %s\n", ssh_err(ret)); } ``` -------------------------------- ### SSH Buffer Safe Operations Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/README.md Shows how to use the sshbuf library for safe buffer manipulation, including setting maximum size, putting data, retrieving a pointer for transmission, and consuming sent bytes. Always free the buffer when done. ```c struct sshbuf *buf = sshbuf_new(); sshbuf_set_max_size(buf, 8192); // Put data sshbuf_put_u32(buf, 0x01020304); sshbuf_put_string(buf, data, data_len); // Get pointer for network transmission const u_char *ptr = sshbuf_ptr(buf); size_t len = sshbuf_len(buf); sent = send(fd, ptr, len, 0); // Consume sent bytes if (sent > 0) { sshbuf_consume(buf, sent); } sshbuf_free(buf); ``` -------------------------------- ### Initialize SSH Cipher Context Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/cipher.md Initializes a cipher context for encryption or decryption. Ensure key and IV lengths match the cipher's requirements. Returns an error code on failure. ```c int cipher_init(struct sshcipher_ctx **ctxp, const struct sshcipher *cipher, const u_char *key, u_int keylen, const u_char *iv, u_int ivlen, int do_encrypt) ``` ```c struct sshcipher_ctx *ctx = NULL; const struct sshcipher *cipher = cipher_by_name("aes128-ctr"); if (cipher == NULL) return SSH_ERR_NO_CIPHER_ALG_MATCH; u_int keylen = cipher_keylen(cipher); u_int ivlen = cipher_ivlen(cipher); u_char key[16]; // 128 bits u_char iv[16]; // IV size matches cipher block size // Fill key and iv from key derivation int ret = cipher_init(&ctx, cipher, key, keylen, iv, ivlen, 1); if (ret != SSH_ERR_SUCCESS) { fprintf(stderr, "Cipher init failed: %s\n", ssh_err(ret)); return ret; } // Use ctx for encryption cipher_free(ctx); ``` -------------------------------- ### Compression Algorithm Names Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/configuration.md Names for compression algorithms supported by OpenSSH. 'none' indicates no compression. ```text "none" ``` ```text "zlib@openssh.com" ``` -------------------------------- ### Set Host Key Verification Callback Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/ssh-api.md Registers a custom callback function to verify host keys. The callback receives the host key and SSH connection, and should return 0 for acceptance or -1 for failure. ```c int ssh_set_verify_host_key_callback(struct ssh *ssh, int (*cb)(struct sshkey *, struct ssh *)) ``` ```c int verify_hostkey(struct sshkey *key, struct ssh *ssh) { // Custom verification logic if (key_is_known(key)) { return 0; } return -1; } ssh_set_verify_host_key_callback(ssh, verify_hostkey); ``` -------------------------------- ### SSH Connection Management (ssh-api.md) Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/INDEX.md Provides high-level functions for SSH connection initialization and packet handling, including session management, application data, host key verification, and packet processing. ```APIDOC ## SSH Connection Management API ### Description This API provides core functionalities for managing SSH connections, including session initialization, data handling, host key management, and packet processing. ### Functions - **Session Initialization:** `ssh_init()`, `ssh_free()` - **Application Data:** `ssh_set_app_data()`, `ssh_get_app_data()` - **Host Keys:** `ssh_add_hostkey()`, `ssh_set_verify_host_key_callback()` - **Packet Processing:** `ssh_packet_next()`, `ssh_packet_payload()` - **Packet Transmission:** `ssh_packet_put()` - **Input Handling:** `ssh_input_space()`, `ssh_input_append()` - **Output Handling:** `ssh_output_space()`, `ssh_output_ptr()`, `ssh_output_consume()` ### Data Structures - `struct kex_params` - Key exchange parameters - `struct ssh` - SSH connection object ``` -------------------------------- ### Manipulate SSH Buffers Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/README.md Illustrates common operations for creating, freeing, checking length, accessing pointer, and putting/getting unsigned 32-bit integers into SSH buffers. ```c sshbuf_new(); sshbuf_free(buf); sshbuf_len(buf); sshbuf_ptr(buf); sshbuf_put_u32(buf, val); sshbuf_get_u32(buf, &val); ``` -------------------------------- ### Add SSH Key with Constraints Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/authfd.md Use this function to add a private key to the SSH agent with optional lifetime and confirmation requirements. Specify constraints to restrict key usage to certain destinations. ```c int ssh_add_identity_constrained(int sock, struct sshkey *key, const char *comment, u_int life, u_int confirm, const char *provider, struct dest_constraint **dest_constraints, size_t ndest_constraints) ``` ```c struct sshkey *key = ...; // Private key to add int ret = ssh_add_identity_constrained( agent_fd, key, "my-key-comment", 3600, // 1 hour timeout 0, // No confirmation required NULL, // Default provider NULL, 0 // No constraints ); if (ret != SSH_ERR_SUCCESS) { fprintf(stderr, "Failed to add key to agent: %s\n", ssh_err(ret)); } ``` -------------------------------- ### sshbuf_froms Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/sshbuf.md Creates a read-only buffer from a length-prefixed string in another buffer. Consumes a 4-byte length prefix and string data from the source buffer. Returns zero on success, or a negative SSH_ERR_* error code on failure. ```APIDOC ## sshbuf_froms ### Description Create a read-only buffer from a length-prefixed string in another buffer. ### Parameters #### Path Parameters - **buf** (struct sshbuf *) - Required - Source buffer - **bufp** (struct sshbuf **) - Required - Pointer to store new string buffer ### Returns Zero on success, negative SSH_ERR_* error code on failure. ### Behavior Consumes a 4-byte length prefix and string data from buf, creating a child buffer from that string. ### Throws/Rejects - SSH_ERR_MESSAGE_INCOMPLETE: Not enough data for length prefix - SSH_ERR_STRING_TOO_LARGE: String length exceeds limits ### Example ```c struct sshbuf *parent = sshbuf_new(); sshbuf_put_cstring(parent, "hello world"); struct sshbuf *child = NULL; int ret = sshbuf_froms(parent, &child); if (ret == SSH_ERR_SUCCESS) { size_t len = sshbuf_len(child); const u_char *data = sshbuf_ptr(child); printf("String: %.*s\n", (int)len, (char*)data); sshbuf_free(child); } sshbuf_free(parent); ``` ``` -------------------------------- ### Parse Private Key from File Blob with Passphrase Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/sshkey.md Parses a private key from a file buffer, supporting encrypted keys with a passphrase. Optionally retrieves a comment associated with the key. ```c struct sshbuf *filebuf = sshbuf_from(file_data, file_len); struct sshkey *key = NULL; char *comment = NULL; int ret = sshkey_parse_private_fileblob(filebuf, "my_passphrase", &key, &comment); if (ret == SSH_ERR_SUCCESS) { printf("Loaded key with comment: %s\n", comment ? comment : "(none)"); free(comment); sshkey_free(key); } sshbuf_free(filebuf); ``` -------------------------------- ### Handle Memory Allocation Failure Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/errors.md Demonstrates how to check for and handle memory allocation failures using SSH_ERR_ALLOC_FAIL. This is crucial for robust error handling in C applications using OpenSSH buffer management. ```c struct sshbuf *buf = sshbuf_new(); if (buf == NULL) { fprintf(stderr, "Error: %s\n", ssh_err(SSH_ERR_ALLOC_FAIL)); } ``` -------------------------------- ### Handle Revoked Key Error in OpenSSH Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/errors.md Shows how to detect and report when a key has been revoked, indicated by the SSH_ERR_KEY_REVOKED error code. ```c // SSH_ERR_KEY_REVOKED when key is in the revocation list if (ret == SSH_ERR_KEY_REVOKED) { fprintf(stderr, "This key has been revoked\n"); } ``` -------------------------------- ### Handle Incorrect Passphrase Error in OpenSSH Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/errors.md Demonstrates how to check for and handle the SSH_ERR_KEY_WRONG_PASSPHRASE error when parsing a private key file with an incorrect passphrase. ```c // SSH_ERR_KEY_WRONG_PASSPHRASE when decrypting with incorrect passphrase struct sshkey *key = NULL; int ret = sshkey_parse_private_fileblob(filebuf, "wrong_pass", &key, NULL); if (ret == SSH_ERR_KEY_WRONG_PASSPHRASE) { fprintf(stderr, "Incorrect passphrase\n"); } ``` -------------------------------- ### Sign Data with SSH Key Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/sshkey.md Use this function to sign arbitrary data using a private SSH key. Specify the algorithm, origin, provider, and flags as needed. Ensure the key is loaded and the output buffers are correctly managed. ```c int sshkey_sign(struct sshkey *key, u_char **sig, size_t *siglen, const u_char *data, size_t datalen, const char *alg, const char *origin, const char *provider, u_int flags) ``` ```c u_char challenge[] = {...}; u_char *signature = NULL; size_t sig_len = 0; int ret = sshkey_sign(key, &signature, &sig_len, challenge, sizeof(challenge), NULL, NULL, NULL, 0); if (ret == SSH_ERR_SUCCESS) { // Use signature free(signature); } ``` -------------------------------- ### Key Exchange Algorithm Negotiation Sequence Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/errors.md Illustrates the common error checks during the key exchange algorithm negotiation phase. It specifically checks for mismatches in cipher or key exchange algorithms before reporting a general key exchange failure. ```c // Typical sequence during algorithm negotiation int ret = kex_exchange(ssh); if (ret == SSH_ERR_NO_CIPHER_ALG_MATCH) { fprintf(stderr, "No common cipher algorithm\n"); } else if (ret == SSH_ERR_NO_KEX_ALG_MATCH) { fprintf(stderr, "No common key exchange algorithm\n"); } else if (ret != SSH_ERR_SUCCESS) { fprintf(stderr, "Key exchange failed: %s\n", ssh_err(ret)); } ``` -------------------------------- ### compression_alg_list Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/cipher.md Generates a string containing a list of all available compression algorithms supported by the system. The `internal_only` parameter can filter this list. ```APIDOC ## compression_alg_list ### Description Generate a list of available compression algorithms. ### Signature const char *compression_alg_list(int internal_only) ### Parameters #### Path Parameters - **internal_only** (int) - Required - Non-zero for internal only ### Returns Static string containing compression algorithm list. ### Example ```c const char *list = compression_alg_list(0); printf("Compression: %s\n", list); ``` ``` -------------------------------- ### Generate OpenSSH Private Key File Source: https://github.com/openssh/openssh-portable/blob/master/regress/unittests/sshsig/webauthn.html Constructs the binary structure for an OpenSSH private key file, including magic, cipher, KDF, and key data. Pads the inner message to an 8-byte block size. ```javascript function privkeyFile(pub, priv, user, rp) { let innerMsg = new SSHMSG() innerMsg.putU32(0xdeadbeef) // check byte innerMsg.putU32(0xdeadbeef) // check byte innerMsg.put(priv) // privkey innerMsg.putString("webauthn.html " + user + "@" + rp) // comment // Pad to cipher blocksize (8). p = 1 while (innerMsg.length() % 8 != 0) { innerMsg.putU8(p++) } let msg = new SSHMSG() msg.putStringRaw("openssh-key-v1") // Magic msg.putU8(0) // \0 terminate msg.putString("none") // cipher msg.putString("none") // KDF msg.putString("") // KDF options msg.putU32(1) // nkeys msg.putBytes(pub) // pubkey msg.putSSHMSG(innerMsg) // inner //msg.put(innerMsg.serialise()) // inner return msg.serialise() } ``` -------------------------------- ### Generate Cipher Algorithm List Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/api-reference/cipher.md This function generates a string containing a list of available cipher algorithms, separated by a specified character. Remember to free the returned string after use. ```c char *cipher_alg_list(char separator, int internal_only) ``` ```c char *list = cipher_alg_list(',', 0); if (list != NULL) { printf("Available ciphers:\n%s\n", list); free(list); } ``` -------------------------------- ### Define Key Derivation Sizes Source: https://github.com/openssh/openssh-portable/blob/master/_autodocs/configuration.md Constants defining the byte sizes for cryptographic keys and public keys used in key derivation processes. ```c #define CURVE25519_SIZE 32 /* Curve25519 public key size (bytes) */ #define ED25519_SK_SZ crypto_sign_ed25519_SECRETKEYBYTES /* 64 bytes */ #define ED25519_PK_SZ crypto_sign_ed25519_PUBLICKEYBYTES /* 32 bytes */ ``` -------------------------------- ### WebAuthn Enrollment Success Handler Source: https://github.com/openssh/openssh-portable/blob/master/regress/unittests/sshsig/webauthn.html Processes the successful result of a WebAuthn enrollment. It decodes and displays client data, raw ID, attestation object, and authenticator data, then reformats the public key into an SSH-compatible format. ```javascript function enrollSuccess(result) { console.log("Enroll succeeded") console.dir(result) window.enrollResult = result document.getElementById("enrollresult").style.visibility = "visible" // Show the clientData let u8dec = new TextDecoder('utf-8') clientData = u8dec.decode(result.response.clientDataJSON) document.getElementById("enrollresultjson").innerText = clientData // Show the raw key handle. document.getElementById("keyhandle").innerText = hexdump(result.rawId) // Decode and show the attestationObject document.getElementById("enrollresultraw").innerText = hexdump(result.response.attestationObject) let aod = new CBORDecode(result.response.attestationObject) let attestationObject = aod.decode() console.log("attestationObject") console.dir(attestationObject) document.getElementById("enrollresultattestobj").innerText = JSON.stringify(attestationObject) // Decode and show the authData document.getElementById("enrollresultauthdataraw").innerText = hexdump(attestationObject.authData) let authData = decodeAuthenticatorData(attestationObject.authData, true) console.log("authData") console.dir(authData) window.enrollAuthData = authData document.getElementById("enrollresultauthdata").innerText = JSON.stringify(authData) // Reformat the pubkey as a SSH key for easy verification window.rawKey = reformatPubkey(authData.attestedCredentialData.credentialPublicKey, window.enrollOpts.rp.id) console.log("SSH pubkey blob") console.dir(window.rawKey) document.getElementById("enrollresultpkblob").innerText = hexdump(window.rawKey) let pk64 = btoa(String.fromCharCode(...new Uint8Array(window.rawKey))); let pk = "sk-ecdsa-sha2-nistp256@openssh.com " + pk64 document.getElementById("enrollresultpk").innerText = pk // Format a private key too. flags = 0x01 // SSH_SK_USER_PRESENCE_REQD window.rawPrivkey = reformatPrivkey(authData.attestedCredentialData.credentialPublicKey, window.enrollOpts.rp.id, result.rawId, flags) let privkeyFileBlob = privkeyFile(window.rawKey, window.rawPrivkey, window.enrollOpts.user.name, window.enrollOpts.rp.id) let privk64 = btoa(String.fromCharCode ```