Statistics
| Branch: | Tag: | Revision:

root / src / libstrongswan / plugins / serpent / serpent_crypter.c @ 315fd57225b35436f2ddcb2f4795efedf5b02d56

History | View | Annotate | Download (4.3 KB)

1
/*
2
 * Copyright (C) JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
3
 * Copyright (C) 2005-2006 Martin Willi
4
 * Copyright (C) 2009 Andreas Steffen
5
 * Hochschule fuer Technik Rapperswil
6
 *
7
 * This program is free software; you can redistribute it and/or modify it
8
 * under the terms of the GNU General Public License as published by the
9
 * Free Software Foundation; either version 2 of the License, or (at your
10
 * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
11
 *
12
 * This program is distributed in the hope that it will be useful, but
13
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15
 * for more details.
16
 */
17
 
18
#include "serpent_crypter.h"
19
#include "serpent.h"
20
21
typedef struct private_serpent_crypter_t private_serpent_crypter_t;
22
23
/**
24
 * Class implementing the Serpent symmetric encryption algorithm.
25
 * 
26
 * @ingroup crypters
27
 */
28
struct private_serpent_crypter_t {
29
    
30
    /**
31
     * Public part of this class.
32
     */
33
    serpent_crypter_t public;
34
    
35
    /**
36
     * Serpent context
37
     */
38
    serpent_context serpent_ctx;
39
    
40
    /**
41
    * Key size of this Serpent cipher object.
42
    */
43
    u_int32_t key_size;
44
};
45
46
/**
47
 * Implementation of crypter_t.encrypt.
48
 */
49
static void encrypt(private_serpent_crypter_t *this, chunk_t data, chunk_t iv,
50
                    chunk_t *encrypted)
51
{
52
    int pos = 0;
53
    u_int8_t *in, *out;
54
    
55
    if (encrypted)
56
    {
57
        *encrypted = chunk_alloc(data.len);
58
        out = encrypted->ptr;
59
    }
60
    else
61
    {
62
        out = data.ptr;
63
    }
64
    in = data.ptr;
65
    
66
    while ( pos < data.len)
67
    {
68
        const u_int32_t *iv_i;
69
70
        iv_i = (pos) ? (const u_int32_t*)(out - 16) :
71
                       (const u_int32_t*)(iv.ptr);
72
        *((u_int32_t *)(&out[ 0])) = iv_i[0] ^ *((const u_int32_t *)(&in[ 0]));
73
        *((u_int32_t *)(&out[ 4])) = iv_i[1] ^ *((const u_int32_t *)(&in[ 4]));
74
        *((u_int32_t *)(&out[ 8])) = iv_i[2] ^ *((const u_int32_t *)(&in[ 8]));
75
        *((u_int32_t *)(&out[12])) = iv_i[3] ^ *((const u_int32_t *)(&in[12]));
76
77
        serpent_encrypt(&this->serpent_ctx, out, out);
78
79
        in  += SERPENT_BLOCK_SIZE;
80
        out += SERPENT_BLOCK_SIZE;
81
        pos += SERPENT_BLOCK_SIZE;
82
    }
83
}
84
85
/**
86
 * Implementation of crypter_t.decrypt.
87
 */
88
static void decrypt(private_serpent_crypter_t *this, chunk_t data, chunk_t iv,
89
                    chunk_t *decrypted)
90
{
91
    int pos = data.len - SERPENT_BLOCK_SIZE;
92
    u_int8_t *in, *out;
93
    
94
    if (decrypted)
95
    {
96
        *decrypted = chunk_alloc(data.len);
97
        out = decrypted->ptr;
98
    }
99
    else
100
    {
101
        out = data.ptr;
102
    }
103
    in = data.ptr;
104
    in  += pos;
105
    out += pos;
106
107
    while (pos >= 0)
108
    {
109
        const u_int32_t *iv_i;
110
111
        serpent_decrypt(&this->serpent_ctx, in, out);
112
113
        iv_i = (pos) ? (const u_int32_t*)(in - 16) :
114
                       (const u_int32_t*)(iv.ptr);
115
        *((u_int32_t *)(&out[ 0])) ^= iv_i[0];
116
        *((u_int32_t *)(&out[ 4])) ^= iv_i[1];
117
        *((u_int32_t *)(&out[ 8])) ^= iv_i[2];
118
        *((u_int32_t *)(&out[12])) ^= iv_i[3];
119
120
        in  -= SERPENT_BLOCK_SIZE;
121
        out -= SERPENT_BLOCK_SIZE;
122
        pos -= SERPENT_BLOCK_SIZE;
123
    }
124
}
125
126
/**
127
 * Implementation of crypter_t.get_block_size.
128
 */
129
static size_t get_block_size (private_serpent_crypter_t *this)
130
{
131
    return SERPENT_BLOCK_SIZE;
132
}
133
134
/**
135
 * Implementation of crypter_t.get_key_size.
136
 */
137
static size_t get_key_size (private_serpent_crypter_t *this)
138
{
139
    return this->key_size;
140
}
141
142
/**
143
 * Implementation of crypter_t.set_key.
144
 */
145
static void set_key (private_serpent_crypter_t *this, chunk_t key)
146
{
147
    serpent_set_key(&this->serpent_ctx, key.ptr, key.len);
148
}
149
150
/**
151
 * Implementation of crypter_t.destroy and serpent_crypter_t.destroy.
152
 */
153
static void destroy (private_serpent_crypter_t *this)
154
{
155
    free(this);
156
}
157
158
/*
159
 * Described in header
160
 */
161
serpent_crypter_t *serpent_crypter_create(encryption_algorithm_t algo, size_t key_size)
162
{
163
    private_serpent_crypter_t *this;
164
    
165
    if (algo != ENCR_SERPENT_CBC || !(key_size == 16 || key_size == 32))
166
    {
167
        return NULL;
168
    }
169
    
170
    this = malloc_thing(private_serpent_crypter_t);
171
    
172
    this->public.crypter_interface.encrypt = (void (*) (crypter_t *, chunk_t,chunk_t, chunk_t *)) encrypt;
173
    this->public.crypter_interface.decrypt = (void (*) (crypter_t *, chunk_t , chunk_t, chunk_t *)) decrypt;
174
    this->public.crypter_interface.get_block_size = (size_t (*) (crypter_t *)) get_block_size;
175
    this->public.crypter_interface.get_key_size = (size_t (*) (crypter_t *)) get_key_size;
176
    this->public.crypter_interface.set_key = (void (*) (crypter_t *,chunk_t)) set_key;
177
    this->public.crypter_interface.destroy = (void (*) (crypter_t *)) destroy;
178
    
179
    return &(this->public);
180
}