~ubuntu-branches/ubuntu/edgy/openssh/edgy

« back to all changes in this revision

Viewing changes to cipher-aes.c

  • Committer: Bazaar Package Importer
  • Author(s): Noah Meyerhans
  • Date: 2006-10-31 17:53:38 UTC
  • Revision ID: james.westby@ubuntu.com-20061031175338-kh299ada2qc2kzlb
Tags: upstream-3.8.1p1
ImportĀ upstreamĀ versionĀ 3.8.1p1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
25
#include "includes.h"
 
26
#if OPENSSL_VERSION_NUMBER < 0x00907000L
 
27
RCSID("$OpenBSD: cipher-aes.c,v 1.2 2003/11/26 21:44:29 djm Exp $");
 
28
 
 
29
#include <openssl/evp.h>
 
30
#include "rijndael.h"
 
31
#include "xmalloc.h"
 
32
#include "log.h"
 
33
 
 
34
#if OPENSSL_VERSION_NUMBER < 0x00906000L
 
35
#define SSH_OLD_EVP
 
36
#endif
 
37
 
 
38
#define RIJNDAEL_BLOCKSIZE 16
 
39
struct ssh_rijndael_ctx
 
40
{
 
41
        rijndael_ctx    r_ctx;
 
42
        u_char          r_iv[RIJNDAEL_BLOCKSIZE];
 
43
};
 
44
 
 
45
const EVP_CIPHER * evp_rijndael(void);
 
46
void ssh_rijndael_iv(EVP_CIPHER_CTX *, int, u_char *, u_int);
 
47
 
 
48
static int
 
49
ssh_rijndael_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
 
50
    int enc)
 
51
{
 
52
        struct ssh_rijndael_ctx *c;
 
53
 
 
54
        if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
 
55
                c = xmalloc(sizeof(*c));
 
56
                EVP_CIPHER_CTX_set_app_data(ctx, c);
 
57
        }
 
58
        if (key != NULL) {
 
59
                if (enc == -1)
 
60
                        enc = ctx->encrypt;
 
61
                rijndael_set_key(&c->r_ctx, (u_char *)key,
 
62
                    8*EVP_CIPHER_CTX_key_length(ctx), enc);
 
63
        }
 
64
        if (iv != NULL)
 
65
                memcpy(c->r_iv, iv, RIJNDAEL_BLOCKSIZE);
 
66
        return (1);
 
67
}
 
68
 
 
69
static int
 
70
ssh_rijndael_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src,
 
71
    u_int len)
 
72
{
 
73
        struct ssh_rijndael_ctx *c;
 
74
        u_char buf[RIJNDAEL_BLOCKSIZE];
 
75
        u_char *cprev, *cnow, *plain, *ivp;
 
76
        int i, j, blocks = len / RIJNDAEL_BLOCKSIZE;
 
77
 
 
78
        if (len == 0)
 
79
                return (1);
 
80
        if (len % RIJNDAEL_BLOCKSIZE)
 
81
                fatal("ssh_rijndael_cbc: bad len %d", len);
 
82
        if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
 
83
                error("ssh_rijndael_cbc: no context");
 
84
                return (0);
 
85
        }
 
86
        if (ctx->encrypt) {
 
87
                cnow  = dest;
 
88
                plain = (u_char *)src;
 
89
                cprev = c->r_iv;
 
90
                for (i = 0; i < blocks; i++, plain+=RIJNDAEL_BLOCKSIZE,
 
91
                    cnow+=RIJNDAEL_BLOCKSIZE) {
 
92
                        for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++)
 
93
                                buf[j] = plain[j] ^ cprev[j];
 
94
                        rijndael_encrypt(&c->r_ctx, buf, cnow);
 
95
                        cprev = cnow;
 
96
                }
 
97
                memcpy(c->r_iv, cprev, RIJNDAEL_BLOCKSIZE);
 
98
        } else {
 
99
                cnow  = (u_char *) (src+len-RIJNDAEL_BLOCKSIZE);
 
100
                plain = dest+len-RIJNDAEL_BLOCKSIZE;
 
101
 
 
102
                memcpy(buf, cnow, RIJNDAEL_BLOCKSIZE);
 
103
                for (i = blocks; i > 0; i--, cnow-=RIJNDAEL_BLOCKSIZE,
 
104
                    plain-=RIJNDAEL_BLOCKSIZE) {
 
105
                        rijndael_decrypt(&c->r_ctx, cnow, plain);
 
106
                        ivp = (i == 1) ? c->r_iv : cnow-RIJNDAEL_BLOCKSIZE;
 
107
                        for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++)
 
108
                                plain[j] ^= ivp[j];
 
109
                }
 
110
                memcpy(c->r_iv, buf, RIJNDAEL_BLOCKSIZE);
 
111
        }
 
112
        return (1);
 
113
}
 
114
 
 
115
static int
 
116
ssh_rijndael_cleanup(EVP_CIPHER_CTX *ctx)
 
117
{
 
118
        struct ssh_rijndael_ctx *c;
 
119
 
 
120
        if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
 
121
                memset(c, 0, sizeof(*c));
 
122
                xfree(c);
 
123
                EVP_CIPHER_CTX_set_app_data(ctx, NULL);
 
124
        }
 
125
        return (1);
 
126
}
 
127
 
 
128
void
 
129
ssh_rijndael_iv(EVP_CIPHER_CTX *evp, int doset, u_char * iv, u_int len)
 
130
{
 
131
        struct ssh_rijndael_ctx *c;
 
132
 
 
133
        if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
 
134
                fatal("ssh_rijndael_iv: no context");
 
135
        if (doset)
 
136
                memcpy(c->r_iv, iv, len);
 
137
        else
 
138
                memcpy(iv, c->r_iv, len);
 
139
}
 
140
 
 
141
const EVP_CIPHER *
 
142
evp_rijndael(void)
 
143
{
 
144
        static EVP_CIPHER rijndal_cbc;
 
145
 
 
146
        memset(&rijndal_cbc, 0, sizeof(EVP_CIPHER));
 
147
        rijndal_cbc.nid = NID_undef;
 
148
        rijndal_cbc.block_size = RIJNDAEL_BLOCKSIZE;
 
149
        rijndal_cbc.iv_len = RIJNDAEL_BLOCKSIZE;
 
150
        rijndal_cbc.key_len = 16;
 
151
        rijndal_cbc.init = ssh_rijndael_init;
 
152
        rijndal_cbc.cleanup = ssh_rijndael_cleanup;
 
153
        rijndal_cbc.do_cipher = ssh_rijndael_cbc;
 
154
#ifndef SSH_OLD_EVP
 
155
        rijndal_cbc.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH |
 
156
            EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV;
 
157
#endif
 
158
        return (&rijndal_cbc);
 
159
}
 
160
#endif /* OPENSSL_VERSION_NUMBER */