/* Targeted runtime checks for the vendored libssh2 security backports. * SPDX-License-Identifier: MIT * This program deliberately supplies boundary lengths, without any network. */ #include #include #include #include #include #include #include "libssh2.h" /* Internal function from the statically linked, patched OpenSSL backend. */ extern int _libssh2_cipher_crypt(EVP_CIPHER_CTX **ctx, const EVP_CIPHER *(*algo)(void), int encrypt, unsigned char *block, size_t blocksize, int firstlast); static int check_crypto_bounds(void) { unsigned char buffer[EVP_MAX_BLOCK_LENGTH + 32]; unsigned char original[sizeof(buffer)]; size_t length; memset(buffer, 0xa5, sizeof(buffer)); memcpy(original, buffer, sizeof(buffer)); /* A complete AES-GCM block requires 4 bytes of AAD plus a 16-byte tag. * A null context makes an accidental call into OpenSSL fail immediately; * a correct bounds check rejects these inputs before touching it. */ for(length = 0; length < 20; length++) { if(_libssh2_cipher_crypt(NULL, EVP_aes_128_gcm, 0, buffer, length, 3) != 1) return 1; } if(_libssh2_cipher_crypt(NULL, EVP_aes_128_gcm, 0, buffer, sizeof(buffer), 3) != 1) return 1; if(_libssh2_cipher_crypt(NULL, EVP_aes_128_gcm, 0, buffer, SIZE_MAX, 3) != 1) return 1; return memcmp(buffer, original, sizeof(buffer)) != 0; } static int check_username_bounds(void) { LIBSSH2_SESSION *session = libssh2_session_init(); int failure = 0; if(!session) return 1; if(libssh2_userauth_list(session, "x", UINT_MAX) != NULL || libssh2_session_last_errno(session) != LIBSSH2_ERROR_PROTO) failure = 1; if(libssh2_userauth_password_ex(session, "x", UINT_MAX, "p", 1, NULL) != LIBSSH2_ERROR_PROTO) failure = 1; libssh2_session_free(session); return failure; } int main(void) { int failure; if(libssh2_init(0) != 0) return 1; failure = check_crypto_bounds() | check_username_bounds(); libssh2_exit(); if(failure) { fputs("libssh2 security boundary regression failed\n", stderr); return 1; } puts("libssh2 security boundaries: AES-GCM short/oversized blocks and overflowing username lengths PASS"); return 0; }