1d059297112922cabb0c674840589be8db821fd9aAdam Langley/* $OpenBSD: cipher.c,v 1.100 2015/01/14 10:29:45 djm Exp $ */ 2bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 3bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Author: Tatu Ylonen <ylo@cs.hut.fi> 4bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 5bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * All rights reserved 6bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 7bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * As far as I am concerned, the code I have written for this software 8bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * can be used freely for any purpose. Any derived versions of this 9bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * software must be clearly marked as such, and if the derived work is 10bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * incompatible with the protocol description in the RFC file, it must be 11bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * called by a name other than "ssh" or "Secure Shell". 12bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 13bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 14bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Copyright (c) 1999 Niels Provos. All rights reserved. 15bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Copyright (c) 1999, 2000 Markus Friedl. All rights reserved. 16bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 17bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Redistribution and use in source and binary forms, with or without 18bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * modification, are permitted provided that the following conditions 19bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * are met: 20bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 1. Redistributions of source code must retain the above copyright 21bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * notice, this list of conditions and the following disclaimer. 22bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 2. Redistributions in binary form must reproduce the above copyright 23bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * notice, this list of conditions and the following disclaimer in the 24bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * documentation and/or other materials provided with the distribution. 25bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 26bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 27bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 28bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 29bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 30bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 31bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 37bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 38bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "includes.h" 39bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 40bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <sys/types.h> 41bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 42bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <string.h> 43bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <stdarg.h> 44d059297112922cabb0c674840589be8db821fd9aAdam Langley#include <stdio.h> 45bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 46bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "cipher.h" 47d059297112922cabb0c674840589be8db821fd9aAdam Langley#include "misc.h" 48d059297112922cabb0c674840589be8db821fd9aAdam Langley#include "sshbuf.h" 49d059297112922cabb0c674840589be8db821fd9aAdam Langley#include "ssherr.h" 50d059297112922cabb0c674840589be8db821fd9aAdam Langley#include "digest.h" 51bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 52bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "openbsd-compat/openssl-compat.h" 53bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 54d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef WITH_SSH1 55bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanextern const EVP_CIPHER *evp_ssh1_bf(void); 56bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanextern const EVP_CIPHER *evp_ssh1_3des(void); 57d059297112922cabb0c674840589be8db821fd9aAdam Langleyextern int ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); 58d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 59bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 60d059297112922cabb0c674840589be8db821fd9aAdam Langleystruct sshcipher { 61bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *name; 62bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int number; /* for ssh1 only */ 63bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int block_size; 64bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int key_len; 65d059297112922cabb0c674840589be8db821fd9aAdam Langley u_int iv_len; /* defaults to block_size */ 66d059297112922cabb0c674840589be8db821fd9aAdam Langley u_int auth_len; 67bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int discard_len; 68d059297112922cabb0c674840589be8db821fd9aAdam Langley u_int flags; 69d059297112922cabb0c674840589be8db821fd9aAdam Langley#define CFLAG_CBC (1<<0) 70d059297112922cabb0c674840589be8db821fd9aAdam Langley#define CFLAG_CHACHAPOLY (1<<1) 71d059297112922cabb0c674840589be8db821fd9aAdam Langley#define CFLAG_AESCTR (1<<2) 72d059297112922cabb0c674840589be8db821fd9aAdam Langley#define CFLAG_NONE (1<<3) 73d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef WITH_OPENSSL 74bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const EVP_CIPHER *(*evptype)(void); 75d059297112922cabb0c674840589be8db821fd9aAdam Langley#else 76d059297112922cabb0c674840589be8db821fd9aAdam Langley void *ignored; 77d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 78d059297112922cabb0c674840589be8db821fd9aAdam Langley}; 79d059297112922cabb0c674840589be8db821fd9aAdam Langley 80d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic const struct sshcipher ciphers[] = { 81d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef WITH_SSH1 82d059297112922cabb0c674840589be8db821fd9aAdam Langley { "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc }, 83d059297112922cabb0c674840589be8db821fd9aAdam Langley { "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des }, 84d059297112922cabb0c674840589be8db821fd9aAdam Langley { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, 0, 0, 1, evp_ssh1_bf }, 85d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif /* WITH_SSH1 */ 86d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef WITH_OPENSSL 87d059297112922cabb0c674840589be8db821fd9aAdam Langley { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null }, 88d059297112922cabb0c674840589be8db821fd9aAdam Langley#if !defined(ANDROID) 89d059297112922cabb0c674840589be8db821fd9aAdam Langley { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc }, 90d059297112922cabb0c674840589be8db821fd9aAdam Langley { "blowfish-cbc", 91d059297112922cabb0c674840589be8db821fd9aAdam Langley SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_bf_cbc }, 92d059297112922cabb0c674840589be8db821fd9aAdam Langley { "cast128-cbc", 93d059297112922cabb0c674840589be8db821fd9aAdam Langley SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_cast5_cbc }, 94bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 95d059297112922cabb0c674840589be8db821fd9aAdam Langley { "arcfour", SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 0, EVP_rc4 }, 96d059297112922cabb0c674840589be8db821fd9aAdam Langley { "arcfour128", SSH_CIPHER_SSH2, 8, 16, 0, 0, 1536, 0, EVP_rc4 }, 97d059297112922cabb0c674840589be8db821fd9aAdam Langley { "arcfour256", SSH_CIPHER_SSH2, 8, 32, 0, 0, 1536, 0, EVP_rc4 }, 98d059297112922cabb0c674840589be8db821fd9aAdam Langley { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 1, EVP_aes_128_cbc }, 99d059297112922cabb0c674840589be8db821fd9aAdam Langley { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 1, EVP_aes_192_cbc }, 100d059297112922cabb0c674840589be8db821fd9aAdam Langley { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 1, EVP_aes_256_cbc }, 101bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman { "rijndael-cbc@lysator.liu.se", 102d059297112922cabb0c674840589be8db821fd9aAdam Langley SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 1, EVP_aes_256_cbc }, 103d059297112922cabb0c674840589be8db821fd9aAdam Langley { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 0, EVP_aes_128_ctr }, 104d059297112922cabb0c674840589be8db821fd9aAdam Langley#if !defined(ANDROID) 105d059297112922cabb0c674840589be8db821fd9aAdam Langley { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 0, EVP_aes_192_ctr }, 106bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 107d059297112922cabb0c674840589be8db821fd9aAdam Langley { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 0, EVP_aes_256_ctr }, 108d059297112922cabb0c674840589be8db821fd9aAdam Langley# ifdef OPENSSL_HAVE_EVPGCM 109d059297112922cabb0c674840589be8db821fd9aAdam Langley { "aes128-gcm@openssh.com", 110d059297112922cabb0c674840589be8db821fd9aAdam Langley SSH_CIPHER_SSH2, 16, 16, 12, 16, 0, 0, EVP_aes_128_gcm }, 111d059297112922cabb0c674840589be8db821fd9aAdam Langley { "aes256-gcm@openssh.com", 112d059297112922cabb0c674840589be8db821fd9aAdam Langley SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm }, 113d059297112922cabb0c674840589be8db821fd9aAdam Langley# endif /* OPENSSL_HAVE_EVPGCM */ 114d059297112922cabb0c674840589be8db821fd9aAdam Langley#else /* WITH_OPENSSL */ 115d059297112922cabb0c674840589be8db821fd9aAdam Langley { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, CFLAG_AESCTR, NULL }, 116d059297112922cabb0c674840589be8db821fd9aAdam Langley { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, CFLAG_AESCTR, NULL }, 117d059297112922cabb0c674840589be8db821fd9aAdam Langley { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, CFLAG_AESCTR, NULL }, 118d059297112922cabb0c674840589be8db821fd9aAdam Langley { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, CFLAG_NONE, NULL }, 119d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif /* WITH_OPENSSL */ 120d059297112922cabb0c674840589be8db821fd9aAdam Langley { "chacha20-poly1305@openssh.com", 121d059297112922cabb0c674840589be8db821fd9aAdam Langley SSH_CIPHER_SSH2, 8, 64, 0, 16, 0, CFLAG_CHACHAPOLY, NULL }, 122d059297112922cabb0c674840589be8db821fd9aAdam Langley 123d059297112922cabb0c674840589be8db821fd9aAdam Langley { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL } 124bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}; 125bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 126bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/*--*/ 127bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 128d059297112922cabb0c674840589be8db821fd9aAdam Langley/* Returns a comma-separated list of supported ciphers. */ 129d059297112922cabb0c674840589be8db821fd9aAdam Langleychar * 130d059297112922cabb0c674840589be8db821fd9aAdam Langleycipher_alg_list(char sep, int auth_only) 131d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 132d059297112922cabb0c674840589be8db821fd9aAdam Langley char *tmp, *ret = NULL; 133d059297112922cabb0c674840589be8db821fd9aAdam Langley size_t nlen, rlen = 0; 134d059297112922cabb0c674840589be8db821fd9aAdam Langley const struct sshcipher *c; 135d059297112922cabb0c674840589be8db821fd9aAdam Langley 136d059297112922cabb0c674840589be8db821fd9aAdam Langley for (c = ciphers; c->name != NULL; c++) { 137d059297112922cabb0c674840589be8db821fd9aAdam Langley if (c->number != SSH_CIPHER_SSH2) 138d059297112922cabb0c674840589be8db821fd9aAdam Langley continue; 139d059297112922cabb0c674840589be8db821fd9aAdam Langley if (auth_only && c->auth_len == 0) 140d059297112922cabb0c674840589be8db821fd9aAdam Langley continue; 141d059297112922cabb0c674840589be8db821fd9aAdam Langley if (ret != NULL) 142d059297112922cabb0c674840589be8db821fd9aAdam Langley ret[rlen++] = sep; 143d059297112922cabb0c674840589be8db821fd9aAdam Langley nlen = strlen(c->name); 144d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) { 145d059297112922cabb0c674840589be8db821fd9aAdam Langley free(ret); 146d059297112922cabb0c674840589be8db821fd9aAdam Langley return NULL; 147d059297112922cabb0c674840589be8db821fd9aAdam Langley } 148d059297112922cabb0c674840589be8db821fd9aAdam Langley ret = tmp; 149d059297112922cabb0c674840589be8db821fd9aAdam Langley memcpy(ret + rlen, c->name, nlen + 1); 150d059297112922cabb0c674840589be8db821fd9aAdam Langley rlen += nlen; 151d059297112922cabb0c674840589be8db821fd9aAdam Langley } 152d059297112922cabb0c674840589be8db821fd9aAdam Langley return ret; 153d059297112922cabb0c674840589be8db821fd9aAdam Langley} 154d059297112922cabb0c674840589be8db821fd9aAdam Langley 155bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanu_int 156d059297112922cabb0c674840589be8db821fd9aAdam Langleycipher_blocksize(const struct sshcipher *c) 157bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 158bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (c->block_size); 159bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 160bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 161bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanu_int 162d059297112922cabb0c674840589be8db821fd9aAdam Langleycipher_keylen(const struct sshcipher *c) 163bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 164bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (c->key_len); 165bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 166bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 167bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanu_int 168d059297112922cabb0c674840589be8db821fd9aAdam Langleycipher_seclen(const struct sshcipher *c) 169d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 170d059297112922cabb0c674840589be8db821fd9aAdam Langley if (strcmp("3des-cbc", c->name) == 0) 171d059297112922cabb0c674840589be8db821fd9aAdam Langley return 14; 172d059297112922cabb0c674840589be8db821fd9aAdam Langley return cipher_keylen(c); 173d059297112922cabb0c674840589be8db821fd9aAdam Langley} 174d059297112922cabb0c674840589be8db821fd9aAdam Langley 175d059297112922cabb0c674840589be8db821fd9aAdam Langleyu_int 176d059297112922cabb0c674840589be8db821fd9aAdam Langleycipher_authlen(const struct sshcipher *c) 177d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 178d059297112922cabb0c674840589be8db821fd9aAdam Langley return (c->auth_len); 179d059297112922cabb0c674840589be8db821fd9aAdam Langley} 180d059297112922cabb0c674840589be8db821fd9aAdam Langley 181d059297112922cabb0c674840589be8db821fd9aAdam Langleyu_int 182d059297112922cabb0c674840589be8db821fd9aAdam Langleycipher_ivlen(const struct sshcipher *c) 183d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 184d059297112922cabb0c674840589be8db821fd9aAdam Langley /* 185d059297112922cabb0c674840589be8db821fd9aAdam Langley * Default is cipher block size, except for chacha20+poly1305 that 186d059297112922cabb0c674840589be8db821fd9aAdam Langley * needs no IV. XXX make iv_len == -1 default? 187d059297112922cabb0c674840589be8db821fd9aAdam Langley */ 188d059297112922cabb0c674840589be8db821fd9aAdam Langley return (c->iv_len != 0 || (c->flags & CFLAG_CHACHAPOLY) != 0) ? 189d059297112922cabb0c674840589be8db821fd9aAdam Langley c->iv_len : c->block_size; 190d059297112922cabb0c674840589be8db821fd9aAdam Langley} 191d059297112922cabb0c674840589be8db821fd9aAdam Langley 192d059297112922cabb0c674840589be8db821fd9aAdam Langleyu_int 193d059297112922cabb0c674840589be8db821fd9aAdam Langleycipher_get_number(const struct sshcipher *c) 194bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 195bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (c->number); 196bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 197bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 198bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanu_int 199d059297112922cabb0c674840589be8db821fd9aAdam Langleycipher_is_cbc(const struct sshcipher *c) 200bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 201d059297112922cabb0c674840589be8db821fd9aAdam Langley return (c->flags & CFLAG_CBC) != 0; 202bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 203bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 204bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanu_int 205bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmancipher_mask_ssh1(int client) 206bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 207bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int mask = 0; 208bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */ 209bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman mask |= 1 << SSH_CIPHER_BLOWFISH; 210bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (client) { 211bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman mask |= 1 << SSH_CIPHER_DES; 212bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 213bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return mask; 214bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 215bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 216d059297112922cabb0c674840589be8db821fd9aAdam Langleyconst struct sshcipher * 217bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmancipher_by_name(const char *name) 218bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 219d059297112922cabb0c674840589be8db821fd9aAdam Langley const struct sshcipher *c; 220bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (c = ciphers; c->name != NULL; c++) 221bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (strcmp(c->name, name) == 0) 222bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return c; 223bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return NULL; 224bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 225bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 226d059297112922cabb0c674840589be8db821fd9aAdam Langleyconst struct sshcipher * 227bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmancipher_by_number(int id) 228bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 229d059297112922cabb0c674840589be8db821fd9aAdam Langley const struct sshcipher *c; 230bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (c = ciphers; c->name != NULL; c++) 231bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (c->number == id) 232bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return c; 233bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return NULL; 234bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 235bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 236bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#define CIPHER_SEP "," 237bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 238bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanciphers_valid(const char *names) 239bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 240d059297112922cabb0c674840589be8db821fd9aAdam Langley const struct sshcipher *c; 241bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *cipher_list, *cp; 242bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *p; 243bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 244bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (names == NULL || strcmp(names, "") == 0) 245bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 0; 246d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((cipher_list = cp = strdup(names)) == NULL) 247d059297112922cabb0c674840589be8db821fd9aAdam Langley return 0; 248bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0'; 249bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (p = strsep(&cp, CIPHER_SEP))) { 250bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman c = cipher_by_name(p); 251bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (c == NULL || c->number != SSH_CIPHER_SSH2) { 252d059297112922cabb0c674840589be8db821fd9aAdam Langley free(cipher_list); 253bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 0; 254bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 255bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 256d059297112922cabb0c674840589be8db821fd9aAdam Langley free(cipher_list); 257bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 1; 258bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 259bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 260bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 261bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Parses the name of the cipher. Returns the number of the corresponding 262bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * cipher, or -1 on error. 263bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 264bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 265bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 266bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmancipher_number(const char *name) 267bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 268d059297112922cabb0c674840589be8db821fd9aAdam Langley const struct sshcipher *c; 269bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (name == NULL) 270bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return -1; 271bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (c = ciphers; c->name != NULL; c++) 272bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (strcasecmp(c->name, name) == 0) 273bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return c->number; 274bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return -1; 275bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 276bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 277bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchar * 278bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmancipher_name(int id) 279bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 280d059297112922cabb0c674840589be8db821fd9aAdam Langley const struct sshcipher *c = cipher_by_number(id); 281bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (c==NULL) ? "<unknown>" : c->name; 282bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 283bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 284d059297112922cabb0c674840589be8db821fd9aAdam Langleyconst char * 285d059297112922cabb0c674840589be8db821fd9aAdam Langleycipher_warning_message(const struct sshcipher_ctx *cc) 286d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 287d059297112922cabb0c674840589be8db821fd9aAdam Langley if (cc == NULL || cc->cipher == NULL) 288d059297112922cabb0c674840589be8db821fd9aAdam Langley return NULL; 289d059297112922cabb0c674840589be8db821fd9aAdam Langley if (cc->cipher->number == SSH_CIPHER_DES) 290d059297112922cabb0c674840589be8db821fd9aAdam Langley return "use of DES is strongly discouraged due to " 291d059297112922cabb0c674840589be8db821fd9aAdam Langley "cryptographic weaknesses"; 292d059297112922cabb0c674840589be8db821fd9aAdam Langley return NULL; 293d059297112922cabb0c674840589be8db821fd9aAdam Langley} 294d059297112922cabb0c674840589be8db821fd9aAdam Langley 295d059297112922cabb0c674840589be8db821fd9aAdam Langleyint 296d059297112922cabb0c674840589be8db821fd9aAdam Langleycipher_init(struct sshcipher_ctx *cc, const struct sshcipher *cipher, 297bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const u_char *key, u_int keylen, const u_char *iv, u_int ivlen, 298bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int do_encrypt) 299bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 300d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef WITH_OPENSSL 301d059297112922cabb0c674840589be8db821fd9aAdam Langley int ret = SSH_ERR_INTERNAL_ERROR; 302bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const EVP_CIPHER *type; 303bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int klen; 304bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_char *junk, *discard; 305bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 306bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (cipher->number == SSH_CIPHER_DES) { 307bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (keylen > 8) 308bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman keylen = 8; 309bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 310d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 311bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman cc->plaintext = (cipher->number == SSH_CIPHER_NONE); 312d059297112922cabb0c674840589be8db821fd9aAdam Langley cc->encrypt = do_encrypt; 313bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 314d059297112922cabb0c674840589be8db821fd9aAdam Langley if (keylen < cipher->key_len || 315d059297112922cabb0c674840589be8db821fd9aAdam Langley (iv != NULL && ivlen < cipher_ivlen(cipher))) 316d059297112922cabb0c674840589be8db821fd9aAdam Langley return SSH_ERR_INVALID_ARGUMENT; 317bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 318d059297112922cabb0c674840589be8db821fd9aAdam Langley cc->cipher = cipher; 319d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { 320d059297112922cabb0c674840589be8db821fd9aAdam Langley return chachapoly_init(&cc->cp_ctx, key, keylen); 321d059297112922cabb0c674840589be8db821fd9aAdam Langley } 322d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifndef WITH_OPENSSL 323d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((cc->cipher->flags & CFLAG_AESCTR) != 0) { 324d059297112922cabb0c674840589be8db821fd9aAdam Langley aesctr_keysetup(&cc->ac_ctx, key, 8 * keylen, 8 * ivlen); 325d059297112922cabb0c674840589be8db821fd9aAdam Langley aesctr_ivsetup(&cc->ac_ctx, iv); 326d059297112922cabb0c674840589be8db821fd9aAdam Langley return 0; 327bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 328d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((cc->cipher->flags & CFLAG_NONE) != 0) 329d059297112922cabb0c674840589be8db821fd9aAdam Langley return 0; 330d059297112922cabb0c674840589be8db821fd9aAdam Langley return SSH_ERR_INVALID_ARGUMENT; 331bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#else 332d059297112922cabb0c674840589be8db821fd9aAdam Langley type = (*cipher->evptype)(); 333d059297112922cabb0c674840589be8db821fd9aAdam Langley EVP_CIPHER_CTX_init(&cc->evp); 334bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv, 335d059297112922cabb0c674840589be8db821fd9aAdam Langley (do_encrypt == CIPHER_ENCRYPT)) == 0) { 336d059297112922cabb0c674840589be8db821fd9aAdam Langley ret = SSH_ERR_LIBCRYPTO_ERROR; 337d059297112922cabb0c674840589be8db821fd9aAdam Langley goto bad; 338d059297112922cabb0c674840589be8db821fd9aAdam Langley } 339d059297112922cabb0c674840589be8db821fd9aAdam Langley if (cipher_authlen(cipher) && 340d059297112922cabb0c674840589be8db821fd9aAdam Langley !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_IV_FIXED, 341d059297112922cabb0c674840589be8db821fd9aAdam Langley -1, (u_char *)iv)) { 342d059297112922cabb0c674840589be8db821fd9aAdam Langley ret = SSH_ERR_LIBCRYPTO_ERROR; 343d059297112922cabb0c674840589be8db821fd9aAdam Langley goto bad; 344d059297112922cabb0c674840589be8db821fd9aAdam Langley } 345bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman klen = EVP_CIPHER_CTX_key_length(&cc->evp); 346bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (klen > 0 && keylen != (u_int)klen) { 347d059297112922cabb0c674840589be8db821fd9aAdam Langley if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0) { 348d059297112922cabb0c674840589be8db821fd9aAdam Langley ret = SSH_ERR_LIBCRYPTO_ERROR; 349d059297112922cabb0c674840589be8db821fd9aAdam Langley goto bad; 350d059297112922cabb0c674840589be8db821fd9aAdam Langley } 351d059297112922cabb0c674840589be8db821fd9aAdam Langley } 352d059297112922cabb0c674840589be8db821fd9aAdam Langley if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0) { 353d059297112922cabb0c674840589be8db821fd9aAdam Langley ret = SSH_ERR_LIBCRYPTO_ERROR; 354d059297112922cabb0c674840589be8db821fd9aAdam Langley goto bad; 355bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 356bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 357bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (cipher->discard_len > 0) { 358d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((junk = malloc(cipher->discard_len)) == NULL || 359d059297112922cabb0c674840589be8db821fd9aAdam Langley (discard = malloc(cipher->discard_len)) == NULL) { 360d059297112922cabb0c674840589be8db821fd9aAdam Langley if (junk != NULL) 361d059297112922cabb0c674840589be8db821fd9aAdam Langley free(junk); 362d059297112922cabb0c674840589be8db821fd9aAdam Langley ret = SSH_ERR_ALLOC_FAIL; 363d059297112922cabb0c674840589be8db821fd9aAdam Langley goto bad; 364d059297112922cabb0c674840589be8db821fd9aAdam Langley } 365d059297112922cabb0c674840589be8db821fd9aAdam Langley ret = EVP_Cipher(&cc->evp, discard, junk, cipher->discard_len); 366d059297112922cabb0c674840589be8db821fd9aAdam Langley explicit_bzero(discard, cipher->discard_len); 367d059297112922cabb0c674840589be8db821fd9aAdam Langley free(junk); 368d059297112922cabb0c674840589be8db821fd9aAdam Langley free(discard); 369d059297112922cabb0c674840589be8db821fd9aAdam Langley if (ret != 1) { 370d059297112922cabb0c674840589be8db821fd9aAdam Langley ret = SSH_ERR_LIBCRYPTO_ERROR; 371d059297112922cabb0c674840589be8db821fd9aAdam Langley bad: 372d059297112922cabb0c674840589be8db821fd9aAdam Langley EVP_CIPHER_CTX_cleanup(&cc->evp); 373d059297112922cabb0c674840589be8db821fd9aAdam Langley return ret; 374d059297112922cabb0c674840589be8db821fd9aAdam Langley } 375bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 376d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 377d059297112922cabb0c674840589be8db821fd9aAdam Langley return 0; 378bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 379bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 380d059297112922cabb0c674840589be8db821fd9aAdam Langley/* 381d059297112922cabb0c674840589be8db821fd9aAdam Langley * cipher_crypt() operates as following: 382d059297112922cabb0c674840589be8db821fd9aAdam Langley * Copy 'aadlen' bytes (without en/decryption) from 'src' to 'dest'. 383d059297112922cabb0c674840589be8db821fd9aAdam Langley * Theses bytes are treated as additional authenticated data for 384d059297112922cabb0c674840589be8db821fd9aAdam Langley * authenticated encryption modes. 385d059297112922cabb0c674840589be8db821fd9aAdam Langley * En/Decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'. 386d059297112922cabb0c674840589be8db821fd9aAdam Langley * Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag. 387d059297112922cabb0c674840589be8db821fd9aAdam Langley * This tag is written on encryption and verified on decryption. 388d059297112922cabb0c674840589be8db821fd9aAdam Langley * Both 'aadlen' and 'authlen' can be set to 0. 389d059297112922cabb0c674840589be8db821fd9aAdam Langley */ 390d059297112922cabb0c674840589be8db821fd9aAdam Langleyint 391d059297112922cabb0c674840589be8db821fd9aAdam Langleycipher_crypt(struct sshcipher_ctx *cc, u_int seqnr, u_char *dest, 392d059297112922cabb0c674840589be8db821fd9aAdam Langley const u_char *src, u_int len, u_int aadlen, u_int authlen) 393bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 394d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { 395d059297112922cabb0c674840589be8db821fd9aAdam Langley return chachapoly_crypt(&cc->cp_ctx, seqnr, dest, src, 396d059297112922cabb0c674840589be8db821fd9aAdam Langley len, aadlen, authlen, cc->encrypt); 397d059297112922cabb0c674840589be8db821fd9aAdam Langley } 398d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifndef WITH_OPENSSL 399d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((cc->cipher->flags & CFLAG_AESCTR) != 0) { 400d059297112922cabb0c674840589be8db821fd9aAdam Langley if (aadlen) 401d059297112922cabb0c674840589be8db821fd9aAdam Langley memcpy(dest, src, aadlen); 402d059297112922cabb0c674840589be8db821fd9aAdam Langley aesctr_encrypt_bytes(&cc->ac_ctx, src + aadlen, 403d059297112922cabb0c674840589be8db821fd9aAdam Langley dest + aadlen, len); 404d059297112922cabb0c674840589be8db821fd9aAdam Langley return 0; 405d059297112922cabb0c674840589be8db821fd9aAdam Langley } 406d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((cc->cipher->flags & CFLAG_NONE) != 0) { 407d059297112922cabb0c674840589be8db821fd9aAdam Langley memcpy(dest, src, aadlen + len); 408d059297112922cabb0c674840589be8db821fd9aAdam Langley return 0; 409d059297112922cabb0c674840589be8db821fd9aAdam Langley } 410d059297112922cabb0c674840589be8db821fd9aAdam Langley return SSH_ERR_INVALID_ARGUMENT; 411d059297112922cabb0c674840589be8db821fd9aAdam Langley#else 412d059297112922cabb0c674840589be8db821fd9aAdam Langley if (authlen) { 413d059297112922cabb0c674840589be8db821fd9aAdam Langley u_char lastiv[1]; 414d059297112922cabb0c674840589be8db821fd9aAdam Langley 415d059297112922cabb0c674840589be8db821fd9aAdam Langley if (authlen != cipher_authlen(cc->cipher)) 416d059297112922cabb0c674840589be8db821fd9aAdam Langley return SSH_ERR_INVALID_ARGUMENT; 417d059297112922cabb0c674840589be8db821fd9aAdam Langley /* increment IV */ 418d059297112922cabb0c674840589be8db821fd9aAdam Langley if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN, 419d059297112922cabb0c674840589be8db821fd9aAdam Langley 1, lastiv)) 420d059297112922cabb0c674840589be8db821fd9aAdam Langley return SSH_ERR_LIBCRYPTO_ERROR; 421d059297112922cabb0c674840589be8db821fd9aAdam Langley /* set tag on decyption */ 422d059297112922cabb0c674840589be8db821fd9aAdam Langley if (!cc->encrypt && 423d059297112922cabb0c674840589be8db821fd9aAdam Langley !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_TAG, 424d059297112922cabb0c674840589be8db821fd9aAdam Langley authlen, (u_char *)src + aadlen + len)) 425d059297112922cabb0c674840589be8db821fd9aAdam Langley return SSH_ERR_LIBCRYPTO_ERROR; 426d059297112922cabb0c674840589be8db821fd9aAdam Langley } 427d059297112922cabb0c674840589be8db821fd9aAdam Langley if (aadlen) { 428d059297112922cabb0c674840589be8db821fd9aAdam Langley if (authlen && 429d059297112922cabb0c674840589be8db821fd9aAdam Langley EVP_Cipher(&cc->evp, NULL, (u_char *)src, aadlen) < 0) 430d059297112922cabb0c674840589be8db821fd9aAdam Langley return SSH_ERR_LIBCRYPTO_ERROR; 431d059297112922cabb0c674840589be8db821fd9aAdam Langley memcpy(dest, src, aadlen); 432d059297112922cabb0c674840589be8db821fd9aAdam Langley } 433bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (len % cc->cipher->block_size) 434d059297112922cabb0c674840589be8db821fd9aAdam Langley return SSH_ERR_INVALID_ARGUMENT; 435d059297112922cabb0c674840589be8db821fd9aAdam Langley if (EVP_Cipher(&cc->evp, dest + aadlen, (u_char *)src + aadlen, 436d059297112922cabb0c674840589be8db821fd9aAdam Langley len) < 0) 437d059297112922cabb0c674840589be8db821fd9aAdam Langley return SSH_ERR_LIBCRYPTO_ERROR; 438d059297112922cabb0c674840589be8db821fd9aAdam Langley if (authlen) { 439d059297112922cabb0c674840589be8db821fd9aAdam Langley /* compute tag (on encrypt) or verify tag (on decrypt) */ 440d059297112922cabb0c674840589be8db821fd9aAdam Langley if (EVP_Cipher(&cc->evp, NULL, NULL, 0) < 0) 441d059297112922cabb0c674840589be8db821fd9aAdam Langley return cc->encrypt ? 442d059297112922cabb0c674840589be8db821fd9aAdam Langley SSH_ERR_LIBCRYPTO_ERROR : SSH_ERR_MAC_INVALID; 443d059297112922cabb0c674840589be8db821fd9aAdam Langley if (cc->encrypt && 444d059297112922cabb0c674840589be8db821fd9aAdam Langley !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_GET_TAG, 445d059297112922cabb0c674840589be8db821fd9aAdam Langley authlen, dest + aadlen + len)) 446d059297112922cabb0c674840589be8db821fd9aAdam Langley return SSH_ERR_LIBCRYPTO_ERROR; 447d059297112922cabb0c674840589be8db821fd9aAdam Langley } 448d059297112922cabb0c674840589be8db821fd9aAdam Langley return 0; 449d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 450bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 451bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 452d059297112922cabb0c674840589be8db821fd9aAdam Langley/* Extract the packet length, including any decryption necessary beforehand */ 453d059297112922cabb0c674840589be8db821fd9aAdam Langleyint 454d059297112922cabb0c674840589be8db821fd9aAdam Langleycipher_get_length(struct sshcipher_ctx *cc, u_int *plenp, u_int seqnr, 455d059297112922cabb0c674840589be8db821fd9aAdam Langley const u_char *cp, u_int len) 456bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 457d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) 458d059297112922cabb0c674840589be8db821fd9aAdam Langley return chachapoly_get_length(&cc->cp_ctx, plenp, seqnr, 459d059297112922cabb0c674840589be8db821fd9aAdam Langley cp, len); 460d059297112922cabb0c674840589be8db821fd9aAdam Langley if (len < 4) 461d059297112922cabb0c674840589be8db821fd9aAdam Langley return SSH_ERR_MESSAGE_INCOMPLETE; 462d059297112922cabb0c674840589be8db821fd9aAdam Langley *plenp = get_u32(cp); 463d059297112922cabb0c674840589be8db821fd9aAdam Langley return 0; 464d059297112922cabb0c674840589be8db821fd9aAdam Langley} 465d059297112922cabb0c674840589be8db821fd9aAdam Langley 466d059297112922cabb0c674840589be8db821fd9aAdam Langleyint 467d059297112922cabb0c674840589be8db821fd9aAdam Langleycipher_cleanup(struct sshcipher_ctx *cc) 468d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 469d059297112922cabb0c674840589be8db821fd9aAdam Langley if (cc == NULL || cc->cipher == NULL) 470d059297112922cabb0c674840589be8db821fd9aAdam Langley return 0; 471d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) 472d059297112922cabb0c674840589be8db821fd9aAdam Langley explicit_bzero(&cc->cp_ctx, sizeof(cc->cp_ctx)); 473d059297112922cabb0c674840589be8db821fd9aAdam Langley else if ((cc->cipher->flags & CFLAG_AESCTR) != 0) 474d059297112922cabb0c674840589be8db821fd9aAdam Langley explicit_bzero(&cc->ac_ctx, sizeof(cc->ac_ctx)); 475d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef WITH_OPENSSL 476d059297112922cabb0c674840589be8db821fd9aAdam Langley else if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0) 477d059297112922cabb0c674840589be8db821fd9aAdam Langley return SSH_ERR_LIBCRYPTO_ERROR; 478d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 479d059297112922cabb0c674840589be8db821fd9aAdam Langley return 0; 480bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 481bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 482bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 483bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Selects the cipher, and keys if by computing the MD5 checksum of the 484bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * passphrase and using the resulting 16 bytes as the key. 485bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 486d059297112922cabb0c674840589be8db821fd9aAdam Langleyint 487d059297112922cabb0c674840589be8db821fd9aAdam Langleycipher_set_key_string(struct sshcipher_ctx *cc, const struct sshcipher *cipher, 488bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const char *passphrase, int do_encrypt) 489bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 490bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_char digest[16]; 491d059297112922cabb0c674840589be8db821fd9aAdam Langley int r = SSH_ERR_INTERNAL_ERROR; 492bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 493d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = ssh_digest_memory(SSH_DIGEST_MD5, 494d059297112922cabb0c674840589be8db821fd9aAdam Langley passphrase, strlen(passphrase), 495d059297112922cabb0c674840589be8db821fd9aAdam Langley digest, sizeof(digest))) != 0) 496d059297112922cabb0c674840589be8db821fd9aAdam Langley goto out; 497bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 498d059297112922cabb0c674840589be8db821fd9aAdam Langley r = cipher_init(cc, cipher, digest, 16, NULL, 0, do_encrypt); 499d059297112922cabb0c674840589be8db821fd9aAdam Langley out: 500d059297112922cabb0c674840589be8db821fd9aAdam Langley explicit_bzero(digest, sizeof(digest)); 501d059297112922cabb0c674840589be8db821fd9aAdam Langley return r; 502bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 503bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 504bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 505d059297112922cabb0c674840589be8db821fd9aAdam Langley * Exports an IV from the sshcipher_ctx required to export the key 506bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * state back from the unprivileged child to the privileged parent 507bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * process. 508bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 509bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 510d059297112922cabb0c674840589be8db821fd9aAdam Langleycipher_get_keyiv_len(const struct sshcipher_ctx *cc) 511bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 512d059297112922cabb0c674840589be8db821fd9aAdam Langley const struct sshcipher *c = cc->cipher; 513d059297112922cabb0c674840589be8db821fd9aAdam Langley int ivlen = 0; 514bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 515bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (c->number == SSH_CIPHER_3DES) 516bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ivlen = 24; 517d059297112922cabb0c674840589be8db821fd9aAdam Langley else if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) 518d059297112922cabb0c674840589be8db821fd9aAdam Langley ivlen = 0; 519d059297112922cabb0c674840589be8db821fd9aAdam Langley else if ((cc->cipher->flags & CFLAG_AESCTR) != 0) 520d059297112922cabb0c674840589be8db821fd9aAdam Langley ivlen = sizeof(cc->ac_ctx.ctr); 521d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef WITH_OPENSSL 522bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman else 523bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp); 524d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif /* WITH_OPENSSL */ 525bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (ivlen); 526bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 527bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 528d059297112922cabb0c674840589be8db821fd9aAdam Langleyint 529d059297112922cabb0c674840589be8db821fd9aAdam Langleycipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, u_int len) 530bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 531d059297112922cabb0c674840589be8db821fd9aAdam Langley const struct sshcipher *c = cc->cipher; 532d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef WITH_OPENSSL 533d059297112922cabb0c674840589be8db821fd9aAdam Langley int evplen; 534d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 535d059297112922cabb0c674840589be8db821fd9aAdam Langley 536d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { 537d059297112922cabb0c674840589be8db821fd9aAdam Langley if (len != 0) 538d059297112922cabb0c674840589be8db821fd9aAdam Langley return SSH_ERR_INVALID_ARGUMENT; 539d059297112922cabb0c674840589be8db821fd9aAdam Langley return 0; 540d059297112922cabb0c674840589be8db821fd9aAdam Langley } 541d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((cc->cipher->flags & CFLAG_AESCTR) != 0) { 542d059297112922cabb0c674840589be8db821fd9aAdam Langley if (len != sizeof(cc->ac_ctx.ctr)) 543d059297112922cabb0c674840589be8db821fd9aAdam Langley return SSH_ERR_INVALID_ARGUMENT; 544d059297112922cabb0c674840589be8db821fd9aAdam Langley memcpy(iv, cc->ac_ctx.ctr, len); 545d059297112922cabb0c674840589be8db821fd9aAdam Langley return 0; 546d059297112922cabb0c674840589be8db821fd9aAdam Langley } 547d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((cc->cipher->flags & CFLAG_NONE) != 0) 548d059297112922cabb0c674840589be8db821fd9aAdam Langley return 0; 549bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 550bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman switch (c->number) { 551d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef WITH_OPENSSL 552bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH_CIPHER_SSH2: 553bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH_CIPHER_DES: 554bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH_CIPHER_BLOWFISH: 555bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman evplen = EVP_CIPHER_CTX_iv_length(&cc->evp); 556d059297112922cabb0c674840589be8db821fd9aAdam Langley if (evplen == 0) 557d059297112922cabb0c674840589be8db821fd9aAdam Langley return 0; 558d059297112922cabb0c674840589be8db821fd9aAdam Langley else if (evplen < 0) 559d059297112922cabb0c674840589be8db821fd9aAdam Langley return SSH_ERR_LIBCRYPTO_ERROR; 560bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((u_int)evplen != len) 561d059297112922cabb0c674840589be8db821fd9aAdam Langley return SSH_ERR_INVALID_ARGUMENT; 562d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifndef OPENSSL_HAVE_EVPCTR 563bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (c->evptype == evp_aes_128_ctr) 564bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ssh_aes_ctr_iv(&cc->evp, 0, iv, len); 565bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman else 566d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 567d059297112922cabb0c674840589be8db821fd9aAdam Langley if (cipher_authlen(c)) { 568d059297112922cabb0c674840589be8db821fd9aAdam Langley if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN, 569d059297112922cabb0c674840589be8db821fd9aAdam Langley len, iv)) 570d059297112922cabb0c674840589be8db821fd9aAdam Langley return SSH_ERR_LIBCRYPTO_ERROR; 571d059297112922cabb0c674840589be8db821fd9aAdam Langley } else 572bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman memcpy(iv, cc->evp.iv, len); 573bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 574d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 575d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef WITH_SSH1 576bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH_CIPHER_3DES: 577d059297112922cabb0c674840589be8db821fd9aAdam Langley return ssh1_3des_iv(&cc->evp, 0, iv, 24); 578d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 579bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman default: 580d059297112922cabb0c674840589be8db821fd9aAdam Langley return SSH_ERR_INVALID_ARGUMENT; 581bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 582d059297112922cabb0c674840589be8db821fd9aAdam Langley return 0; 583bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 584bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 585d059297112922cabb0c674840589be8db821fd9aAdam Langleyint 586d059297112922cabb0c674840589be8db821fd9aAdam Langleycipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv) 587bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 588d059297112922cabb0c674840589be8db821fd9aAdam Langley const struct sshcipher *c = cc->cipher; 589d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef WITH_OPENSSL 590d059297112922cabb0c674840589be8db821fd9aAdam Langley int evplen = 0; 591d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 592d059297112922cabb0c674840589be8db821fd9aAdam Langley 593d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) 594d059297112922cabb0c674840589be8db821fd9aAdam Langley return 0; 595d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((cc->cipher->flags & CFLAG_NONE) != 0) 596d059297112922cabb0c674840589be8db821fd9aAdam Langley return 0; 597bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 598bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman switch (c->number) { 599d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef WITH_OPENSSL 600bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH_CIPHER_SSH2: 601bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH_CIPHER_DES: 602bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH_CIPHER_BLOWFISH: 603bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman evplen = EVP_CIPHER_CTX_iv_length(&cc->evp); 604d059297112922cabb0c674840589be8db821fd9aAdam Langley if (evplen <= 0) 605d059297112922cabb0c674840589be8db821fd9aAdam Langley return SSH_ERR_LIBCRYPTO_ERROR; 606d059297112922cabb0c674840589be8db821fd9aAdam Langley if (cipher_authlen(c)) { 607d059297112922cabb0c674840589be8db821fd9aAdam Langley /* XXX iv arg is const, but EVP_CIPHER_CTX_ctrl isn't */ 608d059297112922cabb0c674840589be8db821fd9aAdam Langley if (!EVP_CIPHER_CTX_ctrl(&cc->evp, 609d059297112922cabb0c674840589be8db821fd9aAdam Langley EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv)) 610d059297112922cabb0c674840589be8db821fd9aAdam Langley return SSH_ERR_LIBCRYPTO_ERROR; 611d059297112922cabb0c674840589be8db821fd9aAdam Langley } else 612bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman memcpy(cc->evp.iv, iv, evplen); 613bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 614d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 615d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef WITH_SSH1 616bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH_CIPHER_3DES: 617d059297112922cabb0c674840589be8db821fd9aAdam Langley return ssh1_3des_iv(&cc->evp, 1, (u_char *)iv, 24); 618d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 619bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman default: 620d059297112922cabb0c674840589be8db821fd9aAdam Langley return SSH_ERR_INVALID_ARGUMENT; 621bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 622d059297112922cabb0c674840589be8db821fd9aAdam Langley return 0; 623bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 624bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 625d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef WITH_OPENSSL 626bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#define EVP_X_STATE(evp) (evp).cipher_data 627bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#define EVP_X_STATE_LEN(evp) (evp).cipher->ctx_size 628bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 629bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 630bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 631d059297112922cabb0c674840589be8db821fd9aAdam Langleycipher_get_keycontext(const struct sshcipher_ctx *cc, u_char *dat) 632bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 633d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef WITH_OPENSSL 634d059297112922cabb0c674840589be8db821fd9aAdam Langley const struct sshcipher *c = cc->cipher; 635bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int plen = 0; 636bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 637d059297112922cabb0c674840589be8db821fd9aAdam Langley if (c->evptype == EVP_rc4) { 638bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman plen = EVP_X_STATE_LEN(cc->evp); 639bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (dat == NULL) 640bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (plen); 641bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman memcpy(dat, EVP_X_STATE(cc->evp), plen); 642bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 643bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (plen); 644d059297112922cabb0c674840589be8db821fd9aAdam Langley#else 645d059297112922cabb0c674840589be8db821fd9aAdam Langley return 0; 646d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 647bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 648bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 649bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 650d059297112922cabb0c674840589be8db821fd9aAdam Langleycipher_set_keycontext(struct sshcipher_ctx *cc, const u_char *dat) 651bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 652d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef WITH_OPENSSL 653d059297112922cabb0c674840589be8db821fd9aAdam Langley const struct sshcipher *c = cc->cipher; 654bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int plen; 655bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 656d059297112922cabb0c674840589be8db821fd9aAdam Langley if (c->evptype == EVP_rc4) { 657bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman plen = EVP_X_STATE_LEN(cc->evp); 658bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman memcpy(EVP_X_STATE(cc->evp), dat, plen); 659bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 660d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 661bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 662