[BACK]Return to cipher-aes.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Annotation of src/usr.bin/ssh/cipher-aes.c, Revision 1.2

1.1       markus      1: /*
                      2:  * Copyright (c) 2003 Markus Friedl.  All rights reserved.
                      3:  *
                      4:  * Redistribution and use in source and binary forms, with or without
                      5:  * modification, are permitted provided that the following conditions
                      6:  * are met:
                      7:  * 1. Redistributions of source code must retain the above copyright
                      8:  *    notice, this list of conditions and the following disclaimer.
                      9:  * 2. Redistributions in binary form must reproduce the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer in the
                     11:  *    documentation and/or other materials provided with the distribution.
                     12:  *
                     13:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     14:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     15:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     16:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     17:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     18:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     19:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     20:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     21:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     22:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     23:  */
                     24:
1.2     ! djm        25: #include "includes.h"
1.1       markus     26: #if OPENSSL_VERSION_NUMBER < 0x00907000L
1.2     ! djm        27: RCSID("$OpenBSD: cipher-aes.c,v 1.1 2003/05/15 03:08:29 markus Exp $");
1.1       markus     28:
                     29: #include <openssl/evp.h>
                     30: #include "rijndael.h"
                     31: #include "xmalloc.h"
                     32: #include "log.h"
                     33:
                     34: #define RIJNDAEL_BLOCKSIZE 16
                     35: struct ssh_rijndael_ctx
                     36: {
                     37:        rijndael_ctx    r_ctx;
                     38:        u_char          r_iv[RIJNDAEL_BLOCKSIZE];
                     39: };
                     40:
                     41: const EVP_CIPHER * evp_rijndael(void);
                     42: void ssh_rijndael_iv(EVP_CIPHER_CTX *, int, u_char *, u_int);
                     43:
                     44: static int
                     45: ssh_rijndael_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
                     46:     int enc)
                     47: {
                     48:        struct ssh_rijndael_ctx *c;
                     49:
                     50:        if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
                     51:                c = xmalloc(sizeof(*c));
                     52:                EVP_CIPHER_CTX_set_app_data(ctx, c);
                     53:        }
                     54:        if (key != NULL) {
                     55:                if (enc == -1)
                     56:                        enc = ctx->encrypt;
                     57:                rijndael_set_key(&c->r_ctx, (u_char *)key,
                     58:                    8*EVP_CIPHER_CTX_key_length(ctx), enc);
                     59:        }
                     60:        if (iv != NULL)
                     61:                memcpy(c->r_iv, iv, RIJNDAEL_BLOCKSIZE);
                     62:        return (1);
                     63: }
                     64:
                     65: static int
                     66: ssh_rijndael_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src,
                     67:     u_int len)
                     68: {
                     69:        struct ssh_rijndael_ctx *c;
                     70:        u_char buf[RIJNDAEL_BLOCKSIZE];
                     71:        u_char *cprev, *cnow, *plain, *ivp;
                     72:        int i, j, blocks = len / RIJNDAEL_BLOCKSIZE;
                     73:
                     74:        if (len == 0)
                     75:                return (1);
                     76:        if (len % RIJNDAEL_BLOCKSIZE)
                     77:                fatal("ssh_rijndael_cbc: bad len %d", len);
                     78:        if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
                     79:                error("ssh_rijndael_cbc: no context");
                     80:                return (0);
                     81:        }
                     82:        if (ctx->encrypt) {
                     83:                cnow  = dest;
                     84:                plain = (u_char *)src;
                     85:                cprev = c->r_iv;
                     86:                for (i = 0; i < blocks; i++, plain+=RIJNDAEL_BLOCKSIZE,
                     87:                    cnow+=RIJNDAEL_BLOCKSIZE) {
                     88:                        for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++)
                     89:                                buf[j] = plain[j] ^ cprev[j];
                     90:                        rijndael_encrypt(&c->r_ctx, buf, cnow);
                     91:                        cprev = cnow;
                     92:                }
                     93:                memcpy(c->r_iv, cprev, RIJNDAEL_BLOCKSIZE);
                     94:        } else {
                     95:                cnow  = (u_char *) (src+len-RIJNDAEL_BLOCKSIZE);
                     96:                plain = dest+len-RIJNDAEL_BLOCKSIZE;
                     97:
                     98:                memcpy(buf, cnow, RIJNDAEL_BLOCKSIZE);
                     99:                for (i = blocks; i > 0; i--, cnow-=RIJNDAEL_BLOCKSIZE,
                    100:                    plain-=RIJNDAEL_BLOCKSIZE) {
                    101:                        rijndael_decrypt(&c->r_ctx, cnow, plain);
                    102:                        ivp = (i == 1) ? c->r_iv : cnow-RIJNDAEL_BLOCKSIZE;
                    103:                        for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++)
                    104:                                plain[j] ^= ivp[j];
                    105:                }
                    106:                memcpy(c->r_iv, buf, RIJNDAEL_BLOCKSIZE);
                    107:        }
                    108:        return (1);
                    109: }
                    110:
                    111: static int
                    112: ssh_rijndael_cleanup(EVP_CIPHER_CTX *ctx)
                    113: {
                    114:        struct ssh_rijndael_ctx *c;
                    115:
                    116:        if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
                    117:                memset(c, 0, sizeof(*c));
                    118:                xfree(c);
                    119:                EVP_CIPHER_CTX_set_app_data(ctx, NULL);
                    120:        }
                    121:        return (1);
                    122: }
                    123:
                    124: void
                    125: ssh_rijndael_iv(EVP_CIPHER_CTX *evp, int doset, u_char * iv, u_int len)
                    126: {
                    127:        struct ssh_rijndael_ctx *c;
                    128:
                    129:        if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
                    130:                fatal("ssh_rijndael_iv: no context");
                    131:        if (doset)
                    132:                memcpy(c->r_iv, iv, len);
                    133:        else
                    134:                memcpy(iv, c->r_iv, len);
                    135: }
                    136:
                    137: const EVP_CIPHER *
                    138: evp_rijndael(void)
                    139: {
                    140:        static EVP_CIPHER rijndal_cbc;
                    141:
                    142:        memset(&rijndal_cbc, 0, sizeof(EVP_CIPHER));
                    143:        rijndal_cbc.nid = NID_undef;
                    144:        rijndal_cbc.block_size = RIJNDAEL_BLOCKSIZE;
                    145:        rijndal_cbc.iv_len = RIJNDAEL_BLOCKSIZE;
                    146:        rijndal_cbc.key_len = 16;
                    147:        rijndal_cbc.init = ssh_rijndael_init;
                    148:        rijndal_cbc.cleanup = ssh_rijndael_cleanup;
                    149:        rijndal_cbc.do_cipher = ssh_rijndael_cbc;
                    150:        rijndal_cbc.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH |
                    151:            EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV;
                    152:        return (&rijndal_cbc);
                    153: }
                    154: #endif