int sftp_mac_set_read_key(pool *p, const EVP_MD *hash, const BIGNUM *k, const char *h, uint32_t hlen) { const unsigned char *id = NULL; char *buf, *ptr; uint32_t buflen, bufsz, id_len; char letter; size_t blocksz; struct sftp_mac *mac; HMAC_CTX *mac_ctx; switch_read_mac(); mac = &(read_macs[read_mac_idx]); mac_ctx = &(read_ctxs[read_mac_idx]); bufsz = buflen = 1024; ptr = buf = sftp_msg_getbuf(p, bufsz); /* Need to use SSH2-style format of K for the key. */ sftp_msg_write_mpint(&buf, &buflen, k); id_len = sftp_session_get_id(&id); /* HASH(K || H || "E" || session_id) */ letter = 'E'; set_mac_key(mac, hash, ptr, (bufsz - buflen), h, hlen, &letter, id, id_len); #if OPENSSL_VERSION_NUMBER > 0x000907000L HMAC_CTX_init(mac_ctx); # if OPENSSL_VERSION_NUMBER >= 0x10000001L if (HMAC_Init_ex(mac_ctx, mac->key, mac->key_len, mac->digest, NULL) != 1) { pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION, "error initializing HMAC: %s", sftp_crypto_get_errors()); errno = EPERM; return -1; } # else HMAC_Init_ex(mac_ctx, mac->key, mac->key_len, mac->digest, NULL); # endif /* OpenSSL-1.0.0 and later */ #else /* Reset the HMAC context. */ HMAC_Init(mac_ctx, NULL, 0, NULL); HMAC_Init(mac_ctx, mac->key, mac->key_len, mac->digest); #endif if (mac->mac_len == 0) { blocksz = EVP_MD_size(mac->digest); } else { blocksz = mac->mac_len; } pr_memscrub(ptr, bufsz); sftp_mac_set_block_size(blocksz); return 0; }
int sftp_mac_set_write_key(pool *p, const EVP_MD *hash, const BIGNUM *k, const char *h, uint32_t hlen) { const unsigned char *id = NULL; char *buf, *ptr; uint32_t buflen, bufsz, id_len; char letter; struct sftp_mac *mac; HMAC_CTX *mac_ctx; switch_write_mac(); mac = &(write_macs[write_mac_idx]); mac_ctx = &(write_ctxs[write_mac_idx]); bufsz = buflen = 1024; ptr = buf = sftp_msg_getbuf(p, bufsz); /* Need to use SSH2-style format of K for the key. */ sftp_msg_write_mpint(&buf, &buflen, k); id_len = sftp_session_get_id(&id); /* HASH(K || H || "F" || session_id) */ letter = 'F'; set_mac_key(mac, hash, ptr, (bufsz - buflen), h, hlen, &letter, id, id_len); #if OPENSSL_VERSION_NUMBER > 0x000907000L HMAC_CTX_init(mac_ctx); #else /* Reset the HMAC context. */ HMAC_Init(mac_ctx, NULL, 0, NULL); #endif HMAC_Init(mac_ctx, mac->key, mac->key_len, mac->digest); pr_memscrub(ptr, bufsz); return 0; }
int sftp_cipher_set_write_key(pool *p, const EVP_MD *hash, const BIGNUM *k, const char *h, uint32_t hlen) { const unsigned char *id = NULL; unsigned char *buf, *ptr; char letter; uint32_t buflen, bufsz, id_len; int key_len; struct sftp_cipher *cipher; EVP_CIPHER_CTX *cipher_ctx; switch_write_cipher(); cipher = &(write_ciphers[write_cipher_idx]); cipher_ctx = write_ctxs[write_cipher_idx]; /* XXX EVP_CIPHER_CTX_init() first appeared in OpenSSL 0.9.7. What to do * for older OpenSSL installations? */ EVP_CIPHER_CTX_init(cipher_ctx); bufsz = buflen = SFTP_CIPHER_BUFSZ; ptr = buf = sftp_msg_getbuf(p, bufsz); /* Need to use SSH2-style format of K for the IV and key. */ sftp_msg_write_mpint(&buf, &buflen, k); id_len = sftp_session_get_id(&id); /* IV: HASH(K || H || "B" || session_id) */ letter = 'B'; if (set_cipher_iv(cipher, hash, ptr, (bufsz - buflen), h, hlen, &letter, id, id_len) < 0) { pr_memscrub(ptr, bufsz); return -1; } key_len = (int) cipher->key_len; /* Key: HASH(K || H || "D" || session_id) */ letter = 'D'; if (set_cipher_key(cipher, hash, ptr, (bufsz - buflen), h, hlen, &letter, id, id_len) < 0) { pr_memscrub(ptr, bufsz); return -1; } if (EVP_CipherInit(cipher_ctx, cipher->cipher, cipher->key, cipher->iv, 1) != 1) { (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION, "error initializing %s cipher for encryption: %s", cipher->algo, sftp_crypto_get_errors()); pr_memscrub(ptr, bufsz); return -1; } if (key_len > 0) { /* Next, set the key length. */ if (EVP_CIPHER_CTX_set_key_length(cipher_ctx, key_len) != 1) { (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION, "error setting key length (%d bytes) for %s cipher for decryption: %s", key_len, cipher->algo, sftp_crypto_get_errors()); pr_memscrub(ptr, bufsz); return -1; } } if (set_cipher_discarded(cipher, cipher_ctx) < 0) { pr_memscrub(ptr, bufsz); return -1; } pr_memscrub(ptr, bufsz); return 0; }