]> andersk Git - openssh.git/blobdiff - cipher.c
- (stevesk) [auth1.c] fix password auth for protocol 1 when
[openssh.git] / cipher.c
index fa0532ca0ad194702031c4d36ccd007cf37d949e..a9ca99cd7fb9e29c8d8d54830f54b231a7772eeb 100644 (file)
--- a/cipher.c
+++ b/cipher.c
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: cipher.c,v 1.52 2002/02/18 13:05:32 markus Exp $");
+RCSID("$OpenBSD: cipher.c,v 1.54 2002/03/19 10:49:35 markus Exp $");
 
 #include "xmalloc.h"
 #include "log.h"
 #include "cipher.h"
 
-#if OPENSSL_VERSION_NUMBER <= 0x0090600fL
-#define EVP_CIPHER_CTX_get_app_data(e)          ((e)->app_data)
-#endif
 #include <openssl/md5.h>
 #include "rijndael.h"
 
+#if OPENSSL_VERSION_NUMBER < 0x00906000L
+#define SSH_OLD_EVP
+#define EVP_CIPHER_CTX_get_app_data(e)          ((e)->app_data)
+#endif
+
 static EVP_CIPHER *evp_ssh1_3des(void);
 static EVP_CIPHER *evp_ssh1_bf(void);
 static EVP_CIPHER *evp_rijndael(void);
@@ -77,16 +78,21 @@ struct Cipher {
 
 /*--*/
 
-u_int  
+u_int
 cipher_blocksize(Cipher *c)
 {
        return (c->block_size);
 }
-u_int  
+u_int
 cipher_keylen(Cipher *c)
 {
        return (c->key_len);
 }
+u_int
+cipher_get_number(Cipher *c)
+{
+       return (c->number);
+}
 
 u_int
 cipher_mask_ssh1(int client)
@@ -175,7 +181,11 @@ cipher_init(CipherContext *cc, Cipher *cipher,
     int encrypt)
 {
        static int dowarn = 1;
+#ifdef SSH_OLD_EVP
+       EVP_CIPHER *type;
+#else
        const EVP_CIPHER *type;
+#endif
        int klen;
 
        if (cipher->number == SSH_CIPHER_DES) {
@@ -200,7 +210,15 @@ cipher_init(CipherContext *cc, Cipher *cipher,
        type = (*cipher->evptype)();
 
        EVP_CIPHER_CTX_init(&cc->evp);
-#if OPENSSL_VERSION_NUMBER > 0x0090600fL
+#ifdef SSH_OLD_EVP
+       if (type->key_len > 0 && type->key_len != keylen) {
+               debug("cipher_init: set keylen (%d -> %d)",
+                   type->key_len, keylen);
+               type->key_len = keylen;
+       }
+       EVP_CipherInit(&cc->evp, type, (u_char *)key, (u_char *)iv,
+           (encrypt == CIPHER_ENCRYPT));
+#else
        if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv,
            (encrypt == CIPHER_ENCRYPT)) == 0)
                fatal("cipher_init: EVP_CipherInit failed for %s",
@@ -215,9 +233,6 @@ cipher_init(CipherContext *cc, Cipher *cipher,
        if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0)
                fatal("cipher_init: EVP_CipherInit: set key failed for %s",
                    cipher->name);
-#else
-       EVP_CipherInit(&cc->evp, type, (u_char *)key, (u_char *)iv,
-           (encrypt == CIPHER_ENCRYPT));
 #endif
 }
 
@@ -226,22 +241,22 @@ cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
 {
        if (len % cc->cipher->block_size)
                fatal("cipher_encrypt: bad plaintext length %d", len);
-#if OPENSSL_VERSION_NUMBER > 0x0090600fL
+#ifdef SSH_OLD_EVP
+       EVP_Cipher(&cc->evp, dest, (u_char *)src, len);
+#else
        if (EVP_Cipher(&cc->evp, dest, (u_char *)src, len) == 0)
                fatal("evp_crypt: EVP_Cipher failed");
-#else
-       EVP_Cipher(&cc->evp, dest, (u_char *)src, len);
 #endif
 }
 
 void
 cipher_cleanup(CipherContext *cc)
 {
-#if OPENSSL_VERSION_NUMBER > 0x0090600fL
+#ifdef SSH_OLD_EVP
+       EVP_CIPHER_CTX_cleanup(&cc->evp);
+#else
        if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0)
                error("cipher_cleanup: EVP_CIPHER_CTX_cleanup failed");
-#else
-       EVP_CIPHER_CTX_cleanup(&cc->evp);
 #endif
 }
 
@@ -313,7 +328,11 @@ ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
        EVP_CIPHER_CTX_init(&c->k1);
        EVP_CIPHER_CTX_init(&c->k2);
        EVP_CIPHER_CTX_init(&c->k3);
-#if OPENSSL_VERSION_NUMBER > 0x0090600fL
+#ifdef SSH_OLD_EVP
+       EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc);
+       EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc);
+       EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc);
+#else
        if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
            EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
            EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
@@ -322,10 +341,6 @@ ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
                EVP_CIPHER_CTX_set_app_data(ctx, NULL);
                return (0);
        }
-#else
-       EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc);
-       EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc);
-       EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc);
 #endif
        return (1);
 }
@@ -338,15 +353,15 @@ ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len)
                error("ssh1_3des_cbc: no context");
                return (0);
        }
-#if OPENSSL_VERSION_NUMBER > 0x0090600fL
+#ifdef SSH_OLD_EVP
+       EVP_Cipher(&c->k1, dest, (u_char *)src, len);
+       EVP_Cipher(&c->k2, dest, dest, len);
+       EVP_Cipher(&c->k3, dest, dest, len);
+#else
        if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 ||
            EVP_Cipher(&c->k2, dest, dest, len) == 0 ||
            EVP_Cipher(&c->k3, dest, dest, len) == 0)
                return (0);
-#else
-       EVP_Cipher(&c->k1, dest, (u_char *)src, len);
-       EVP_Cipher(&c->k2, dest, dest, len);
-       EVP_Cipher(&c->k3, dest, dest, len);
 #endif
        return (1);
 }
@@ -375,7 +390,7 @@ evp_ssh1_3des(void)
        ssh1_3des.init = ssh1_3des_init;
        ssh1_3des.cleanup = ssh1_3des_cleanup;
        ssh1_3des.do_cipher = ssh1_3des_cbc;
-#if OPENSSL_VERSION_NUMBER > 0x0090600fL
+#ifndef SSH_OLD_EVP
        ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
 #endif
        return (&ssh1_3des);
@@ -525,9 +540,177 @@ evp_rijndael(void)
        rijndal_cbc.init = ssh_rijndael_init;
        rijndal_cbc.cleanup = ssh_rijndael_cleanup;
        rijndal_cbc.do_cipher = ssh_rijndael_cbc;
-#if OPENSSL_VERSION_NUMBER > 0x0090600fL
+#ifndef SSH_OLD_EVP
        rijndal_cbc.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH |
            EVP_CIPH_ALWAYS_CALL_INIT;
 #endif
        return (&rijndal_cbc);
 }
+
+/*
+ * Exports an IV from the CipherContext required to export the key
+ * state back from the unprivileged child to the privileged parent
+ * process.
+ */
+
+int
+cipher_get_keyiv_len(CipherContext *cc)
+{
+       Cipher *c = cc->cipher;
+       int ivlen;
+
+       if (c->number == SSH_CIPHER_3DES)
+               ivlen = 24;
+       else
+               ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp);
+       return (ivlen);
+}
+
+void
+cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len)
+{
+       Cipher *c = cc->cipher;
+       u_char *civ = NULL;
+       int evplen;
+
+       switch (c->number) {
+       case SSH_CIPHER_SSH2:
+       case SSH_CIPHER_DES:
+       case SSH_CIPHER_BLOWFISH:
+               evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
+               if (evplen == 0)
+                       return;
+               if (evplen != len)
+                       fatal("%s: wrong iv length %d != %d", __FUNCTION__,
+                           evplen, len);
+
+               if (strncmp(c->name, "aes", 3) == 0) {
+                       struct ssh_rijndael_ctx *aesc;
+
+                       aesc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
+                       if (aesc == NULL)
+                               fatal("%s: no rijndael context", __FUNCTION__);
+                       civ = aesc->r_iv;
+               } else {
+                       civ = cc->evp.iv;
+               }
+               break;
+       case SSH_CIPHER_3DES: {
+               struct ssh1_3des_ctx *desc;
+               if (len != 24)
+                       fatal("%s: bad 3des iv length: %d", __FUNCTION__, len);
+               desc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
+               if (desc == NULL)
+                       fatal("%s: no 3des context", __FUNCTION__);
+               debug3("%s: Copying 3DES IV", __FUNCTION__);
+               memcpy(iv, desc->k1.iv, 8);
+               memcpy(iv + 8, desc->k2.iv, 8);
+               memcpy(iv + 16, desc->k3.iv, 8);
+               return;
+       }
+       default:
+               fatal("%s: bad cipher %d", __FUNCTION__, c->number);
+       }
+       memcpy(iv, civ, len);
+}
+
+void
+cipher_set_keyiv(CipherContext *cc, u_char *iv)
+{
+       Cipher *c = cc->cipher;
+       u_char *div = NULL;
+       int evplen = 0;
+
+       switch (c->number) {
+       case SSH_CIPHER_SSH2:
+       case SSH_CIPHER_DES:
+       case SSH_CIPHER_BLOWFISH:
+               evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
+               if (evplen == 0)
+                       return;
+
+               if (strncmp(c->name, "aes", 3) == 0) {
+                       struct ssh_rijndael_ctx *aesc;
+
+                       aesc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
+                       if (aesc == NULL)
+                               fatal("%s: no rijndael context", __FUNCTION__);
+                       div = aesc->r_iv;
+               }else {
+                       div = cc->evp.iv;
+               }
+               break;
+       case SSH_CIPHER_3DES: {
+               struct ssh1_3des_ctx *desc;
+               desc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
+               if (desc == NULL)
+                       fatal("%s: no 3des context", __FUNCTION__);
+               debug3("%s: Installed 3DES IV", __FUNCTION__);
+               memcpy(desc->k1.iv, iv, 8);
+               memcpy(desc->k2.iv, iv + 8, 8);
+               memcpy(desc->k3.iv, iv + 16, 8);
+               return;
+       }
+       default:
+               fatal("%s: bad cipher %d", __FUNCTION__, c->number);
+       }
+       memcpy(div, iv, evplen);
+}
+
+#if OPENSSL_VERSION_NUMBER < 0x00907000L
+#define EVP_X_STATE(evp)       &(evp).c
+#define EVP_X_STATE_LEN(evp)   sizeof((evp).c)
+#else
+#define EVP_X_STATE(evp)       (evp).cipher_data
+#define EVP_X_STATE_LEN(evp)   (evp).cipher->ctx_size
+#endif
+
+int
+cipher_get_keycontext(CipherContext *cc, u_char *dat)
+{
+       Cipher *c = cc->cipher;
+       int plen;
+
+       if (c->number == SSH_CIPHER_3DES) {
+               struct ssh1_3des_ctx *desc;
+               desc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
+               if (desc == NULL)
+                       fatal("%s: no 3des context", __FUNCTION__);
+               plen = EVP_X_STATE_LEN(desc->k1);
+               if (dat == NULL)
+                       return (3*plen);
+               memcpy(dat, EVP_X_STATE(desc->k1), plen);
+               memcpy(dat + plen, EVP_X_STATE(desc->k2), plen);
+               memcpy(dat + 2*plen, EVP_X_STATE(desc->k3), plen);
+               return (3*plen);
+       }
+
+       /* Generic EVP */
+       plen = EVP_X_STATE_LEN(cc->evp);
+       if (dat == NULL)
+               return (plen);
+
+       memcpy(dat, EVP_X_STATE(cc->evp), plen);
+       return (plen);
+}
+
+void
+cipher_set_keycontext(CipherContext *cc, u_char *dat)
+{
+       Cipher *c = cc->cipher;
+       int plen;
+
+       if (c->number == SSH_CIPHER_3DES) {
+               struct ssh1_3des_ctx *desc;
+               desc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
+               if (desc == NULL)
+                       fatal("%s: no 3des context", __FUNCTION__);
+               plen = EVP_X_STATE_LEN(desc->k1);
+               memcpy(EVP_X_STATE(desc->k1), dat, plen);
+               memcpy(EVP_X_STATE(desc->k2), dat + plen, plen);
+               memcpy(EVP_X_STATE(desc->k3), dat + 2*plen, plen);
+       } else {
+               plen = EVP_X_STATE_LEN(cc->evp);
+               memcpy(EVP_X_STATE(cc->evp), dat, plen);
+       }
+}
This page took 0.047919 seconds and 4 git commands to generate.