Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

gdp / ep / ep_crypto_cipher.c @ master

History | View | Annotate | Download (6.66 KB)

1 8712047f Eric Allman
/* vim: set ai sw=8 sts=8 ts=8 :*/
2
3 055d3009 Eric Allman
/***********************************************************************
4
**  ----- BEGIN LICENSE BLOCK -----
5
**        LIBEP: Enhanced Portability Library (Reduced Edition)
6
**
7 c87dd166 Eric Allman
**        Copyright (c) 2008-2019, Eric P. Allman.  All rights reserved.
8
**        Copyright (c) 2015-2019, Regents of the University of California.
9 6bd5476b Eric Allman
**        All rights reserved.
10 055d3009 Eric Allman
**
11 6bd5476b Eric Allman
**        Permission is hereby granted, without written agreement and without
12
**        license or royalty fees, to use, copy, modify, and distribute this
13
**        software and its documentation for any purpose, provided that the above
14
**        copyright notice and the following two paragraphs appear in all copies
15
**        of this software.
16 055d3009 Eric Allman
**
17 6bd5476b Eric Allman
**        IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
18
**        SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST
19
**        PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
20
**        EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21 055d3009 Eric Allman
**
22 6bd5476b Eric Allman
**        REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
23 055d3009 Eric Allman
**        LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 6bd5476b Eric Allman
**        FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION,
25
**        IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO
26
**        OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
27
**        OR MODIFICATIONS.
28 055d3009 Eric Allman
**  ----- END LICENSE BLOCK -----
29
***********************************************************************/
30
31 7023c91a Eric Allman
/*
32
**  Symmetric cipher support.
33
*/
34
35 bc8f5773 Eric Allman
#include <ep/ep.h>
36 8712047f Eric Allman
#include <ep/ep_crypto.h>
37
38
struct ep_crypto_cipher_ctx
39
{
40
        EP_CRYPTO_KEY        *key;                // symmetric encryption/decryption key
41 b956b229 Eric Allman
        EVP_CIPHER_CTX        *ctx;                // OpenSSL cipher context
42 8712047f Eric Allman
//        uint8_t                iv[EVP_MAX_IV_LENGTH];
43
};
44
45
46 7023c91a Eric Allman
/*
47
**  Convert EP cipher code to OpenSSL cipher (helper routine)
48
*/
49
50 8712047f Eric Allman
static const EVP_CIPHER *
51
evp_cipher_type(uint32_t cipher)
52
{
53
        switch (cipher)
54
        {
55
          case EP_CRYPTO_SYMKEY_AES128 | EP_CRYPTO_MODE_CBC:
56
                return EVP_aes_128_cbc();
57
          case EP_CRYPTO_SYMKEY_AES128 | EP_CRYPTO_MODE_CFB:
58
                return EVP_aes_128_cfb();
59
          case EP_CRYPTO_SYMKEY_AES128 | EP_CRYPTO_MODE_OFB:
60
                return EVP_aes_128_ofb();
61
62
          case EP_CRYPTO_SYMKEY_AES192 | EP_CRYPTO_MODE_CBC:
63
                return EVP_aes_192_cbc();
64
          case EP_CRYPTO_SYMKEY_AES192 | EP_CRYPTO_MODE_CFB:
65
                return EVP_aes_192_cfb();
66
          case EP_CRYPTO_SYMKEY_AES192 | EP_CRYPTO_MODE_OFB:
67
                return EVP_aes_192_ofb();
68
69
          case EP_CRYPTO_SYMKEY_AES256 | EP_CRYPTO_MODE_CBC:
70
                return EVP_aes_256_cbc();
71
          case EP_CRYPTO_SYMKEY_AES256 | EP_CRYPTO_MODE_CFB:
72
                return EVP_aes_256_cfb();
73
          case EP_CRYPTO_SYMKEY_AES256 | EP_CRYPTO_MODE_OFB:
74
                return EVP_aes_256_ofb();
75
        }
76
77 970aa77d Eric Allman
        (void) _ep_crypto_error(EP_STAT_CRYPTO_KEYTYPE,
78
                        "ep_crypto_cipher_new: unknown cipher type 0x%x",
79 7023c91a Eric Allman
                        cipher);
80 970aa77d Eric Allman
        return NULL;
81 8712047f Eric Allman
}
82
83
84 7023c91a Eric Allman
/*
85
**  Create a new cipher context.  This is used by most of the
86
**  rest of the cipher routines.
87
**
88
**        The 'enc' parameter tells whether this is an encryption or a
89
**        description operation (true == encrypt).
90
**
91
**        XXX need to explain iv.
92
*/
93
94 8712047f Eric Allman
EP_CRYPTO_CIPHER_CTX *
95
ep_crypto_cipher_new(
96
                uint32_t cipher,
97
                uint8_t *key,
98
                uint8_t *iv,
99
                bool enc)
100
{
101
        EP_CRYPTO_CIPHER_CTX *ctx;
102
        const EVP_CIPHER *ciphertype;
103
        ENGINE *engine = NULL;
104
105
        ciphertype = evp_cipher_type(cipher);
106
        if (ciphertype == NULL)
107
                return NULL;
108
109 fc0cbc23 Eric Allman
        ctx = (EP_CRYPTO_CIPHER_CTX *) ep_mem_zalloc(sizeof *ctx);
110 b956b229 Eric Allman
#if OPENSSL_VERSION_NUMBER >= 0x10100000        // version 1.1.0
111
        ctx->ctx = EVP_CIPHER_CTX_new();
112
#else
113
        ctx->ctx = ep_mem_malloc(sizeof *ctx->ctx);
114
        EVP_CIPHER_CTX_init(ctx->ctx);
115
#endif
116
        if (EVP_CipherInit_ex(ctx->ctx, ciphertype, engine, key, iv, enc) <= 0)
117 8712047f Eric Allman
        {
118
                ep_crypto_cipher_free(ctx);
119 970aa77d Eric Allman
                (void) _ep_crypto_error(EP_STAT_CRYPTO_CIPHER,
120
                                "ep_crypto_cipher_new: "
121 7023c91a Eric Allman
                                "cannot initialize for encryption");
122 970aa77d Eric Allman
                return NULL;
123 8712047f Eric Allman
        }
124
125
        return ctx;
126
}
127
128
129 7023c91a Eric Allman
/*
130
**  Free a cipher context
131
**
132
**        This makes sure that sensitive information is cleared from
133
**        memory before it is released.
134
*/
135
136 8712047f Eric Allman
void
137
ep_crypto_cipher_free(EP_CRYPTO_CIPHER_CTX *ctx)
138
{
139 b956b229 Eric Allman
#if OPENSSL_VERSION_NUMBER >= 0x10100000        // version 1.1.0
140 c70b1607 Eric Allman
        EVP_CIPHER_CTX_free(ctx->ctx);
141 b956b229 Eric Allman
#else
142 c70b1607 Eric Allman
        if (EVP_CIPHER_CTX_cleanup(ctx->ctx) <= 0)
143 970aa77d Eric Allman
                (void) _ep_crypto_error(EP_STAT_CRYPTO_FAIL,
144
                                "cannot cleanup cipher context");
145 c70b1607 Eric Allman
        ep_mem_free(ctx->ctx);
146
#endif
147 8712047f Eric Allman
        ep_mem_free(ctx);
148
}
149
150
151 7023c91a Eric Allman
/*
152
**  Do symmetric encryption
153
**
154
**        This can be done using ep_crypto_cipher_crypt, which
155
**        encrypts or decrypts a block of memory and does the final
156
**        padding in one operation, or by calling ep_crypto_cipher_update
157
**        on multiple blocks followed by ep_crypto_cipher_final to
158
**        do the padding.
159
**
160
**        In all cases, the value of a successful status code contains
161
**        the number of bytes actually written to the output.
162
*/
163
164 8712047f Eric Allman
EP_STAT
165
ep_crypto_cipher_crypt(
166
                EP_CRYPTO_CIPHER_CTX *ctx,
167 ce129b30 Eric Allman
                void *_in,
168 8712047f Eric Allman
                size_t inlen,
169 ce129b30 Eric Allman
                void *_out,
170 8712047f Eric Allman
                size_t outlen)
171
{
172 ce129b30 Eric Allman
        uint8_t *in = (uint8_t *) _in;
173
        uint8_t *out = (uint8_t *) _out;
174 8712047f Eric Allman
        int olen;
175
        int rval;
176
177
        // must allow room for final padding in output buffer
178 b956b229 Eric Allman
        if (outlen < inlen + EVP_CIPHER_CTX_key_length(ctx->ctx))
179 8712047f Eric Allman
        {
180
                // potential buffer overflow
181 970aa77d Eric Allman
                return _ep_crypto_error(EP_STAT_BUF_OVERFLOW,
182
                                "cp_crypto_cipher_crypt: "
183 7023c91a Eric Allman
                                "short output buffer (%d < %d + %d)",
184 b956b229 Eric Allman
                        outlen, inlen, EVP_CIPHER_CTX_key_length(ctx->ctx));
185 8712047f Eric Allman
        }
186
187 b956b229 Eric Allman
        if (EVP_CipherUpdate(ctx->ctx, (uint8_t *) out, &olen, (uint8_t *) in, inlen) <= 0)
188 8712047f Eric Allman
        {
189 970aa77d Eric Allman
                return _ep_crypto_error(EP_STAT_CRYPTO_CIPHER,
190
                                "ep_crypto_cipher_crypt: "
191 7023c91a Eric Allman
                                "cannot encrypt/decrypt");
192 8712047f Eric Allman
        }
193
        rval = olen;
194
        out += olen;
195 b956b229 Eric Allman
        if (EVP_CipherFinal_ex(ctx->ctx, out, &olen) <= 0)
196 8712047f Eric Allman
        {
197 970aa77d Eric Allman
                return _ep_crypto_error(EP_STAT_CRYPTO_CIPHER,
198
                                "ep_crypto_cipher_crypt: "
199 7023c91a Eric Allman
                                "cannot finalize encrypt/decrypt");
200 8712047f Eric Allman
        }
201
202
        rval += olen;
203 2a8cda22 Eric Allman
        EP_ASSERT(rval >= 0);
204 8712047f Eric Allman
        return EP_STAT_FROM_INT(rval);
205
}
206
207
208
EP_STAT
209 7023c91a Eric Allman
ep_crypto_cipher_update(
210 8712047f Eric Allman
                EP_CRYPTO_CIPHER_CTX *ctx,
211 fc0cbc23 Eric Allman
                void *_in,
212 8712047f Eric Allman
                size_t inlen,
213 fc0cbc23 Eric Allman
                void *_out,
214 8712047f Eric Allman
                size_t outlen)
215
{
216 fc0cbc23 Eric Allman
        uint8_t *in = (uint8_t *) _in;
217
        uint8_t *out = (uint8_t *) _out;
218 8712047f Eric Allman
        int olen;
219
220 b956b229 Eric Allman
        if (EVP_CipherUpdate(ctx->ctx, out, &olen, in, inlen) <= 0)
221 8712047f Eric Allman
        {
222 970aa77d Eric Allman
                return _ep_crypto_error(EP_STAT_CRYPTO_CIPHER,
223
                                "ep_crypto_cipher_update: "
224 7023c91a Eric Allman
                                "cannot encrypt/decrypt");
225 8712047f Eric Allman
        }
226
227 fc0cbc23 Eric Allman
        EP_ASSERT(olen >= 0 && (unsigned) olen <= outlen);
228 8712047f Eric Allman
        return EP_STAT_FROM_INT(olen);
229
}
230
231
232
EP_STAT
233 7023c91a Eric Allman
ep_crypto_cipher_final(
234 8712047f Eric Allman
                EP_CRYPTO_CIPHER_CTX *ctx,
235 fc0cbc23 Eric Allman
                void *_out,
236 8712047f Eric Allman
                size_t outlen)
237
{
238 fc0cbc23 Eric Allman
        uint8_t *out = (uint8_t *) _out;
239 8712047f Eric Allman
        int olen;
240
241
        // allow room for possible final padding
242 b956b229 Eric Allman
        if ((ssize_t) outlen < EVP_CIPHER_CTX_key_length(ctx->ctx))
243 8712047f Eric Allman
        {
244
                // potential buffer overflow
245 970aa77d Eric Allman
                return _ep_crypto_error(EP_STAT_BUF_OVERFLOW,
246
                                "ep_crypto_cipher_final: "
247 7023c91a Eric Allman
                                "short output buffer (%d < %d)",
248 b956b229 Eric Allman
                                outlen, EVP_CIPHER_CTX_key_length(ctx->ctx));
249 8712047f Eric Allman
        }
250
251 b956b229 Eric Allman
        if (EVP_CipherFinal_ex(ctx->ctx, out, &olen) <= 0)
252 8712047f Eric Allman
        {
253 970aa77d Eric Allman
                return _ep_crypto_error(EP_STAT_CRYPTO_CIPHER,
254
                                "ep_crypto_cipher_final: "
255 7023c91a Eric Allman
                                "cannot finalize encrypt/decrypt");
256 8712047f Eric Allman
        }
257
258 2a8cda22 Eric Allman
        EP_ASSERT(olen >= 0);
259 8712047f Eric Allman
        return EP_STAT_FROM_INT(olen);
260
}