Fix RC4-MD5 based ciphersuites
[openssl.git] / providers / implementations / ciphers / cipher_aes_wrp.c
1 /*
2  * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 /*
11  * This file uses the low level AES functions (which are deprecated for
12  * non-internal use) in order to implement provider AES ciphers.
13  */
14 #include "internal/deprecated.h"
15
16 #include "cipher_aes.h"
17 #include "prov/providercommon.h"
18 #include "prov/providercommonerr.h"
19 #include "prov/implementations.h"
20
21 /* AES wrap with padding has IV length of 4, without padding 8 */
22 #define AES_WRAP_PAD_IVLEN   4
23 #define AES_WRAP_NOPAD_IVLEN 8
24
25 /* TODO(3.0) Figure out what flags need to be passed */
26 #define WRAP_FLAGS (EVP_CIPH_WRAP_MODE | EVP_CIPH_CUSTOM_IV \
27                     | EVP_CIPH_ALWAYS_CALL_INIT)
28 #define WRAP_FLAGS_INV (WRAP_FLAGS | EVP_CIPH_FLAG_INVERSE_CIPHER)
29
30 typedef size_t (*aeswrap_fn)(void *key, const unsigned char *iv,
31                              unsigned char *out, const unsigned char *in,
32                              size_t inlen, block128_f block);
33
34 static OSSL_FUNC_cipher_encrypt_init_fn aes_wrap_einit;
35 static OSSL_FUNC_cipher_decrypt_init_fn aes_wrap_dinit;
36 static OSSL_FUNC_cipher_update_fn aes_wrap_cipher;
37 static OSSL_FUNC_cipher_final_fn aes_wrap_final;
38 static OSSL_FUNC_cipher_freectx_fn aes_wrap_freectx;
39
40 typedef struct prov_aes_wrap_ctx_st {
41     PROV_CIPHER_CTX base;
42     union {
43         OSSL_UNION_ALIGN;
44         AES_KEY ks;
45     } ks;
46     aeswrap_fn wrapfn;
47
48 } PROV_AES_WRAP_CTX;
49
50
51 static void *aes_wrap_newctx(size_t kbits, size_t blkbits,
52                              size_t ivbits, unsigned int mode, uint64_t flags)
53 {
54     PROV_AES_WRAP_CTX *wctx;
55     PROV_CIPHER_CTX *ctx;
56
57     if (!ossl_prov_is_running())
58         return NULL;
59
60     wctx = OPENSSL_zalloc(sizeof(*wctx));
61     ctx = (PROV_CIPHER_CTX *)wctx;
62     if (ctx != NULL) {
63         ossl_cipher_generic_initkey(ctx, kbits, blkbits, ivbits, mode, flags,
64                                     NULL, NULL);
65         ctx->pad = (ctx->ivlen == AES_WRAP_PAD_IVLEN);
66     }
67     return wctx;
68 }
69
70 static void aes_wrap_freectx(void *vctx)
71 {
72     PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx;
73
74     ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
75     OPENSSL_clear_free(wctx,  sizeof(*wctx));
76 }
77
78 static int aes_wrap_init(void *vctx, const unsigned char *key,
79                          size_t keylen, const unsigned char *iv,
80                          size_t ivlen, int enc)
81 {
82     PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
83     PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx;
84
85     if (!ossl_prov_is_running())
86         return 0;
87
88     ctx->enc = enc;
89     if (ctx->pad)
90         wctx->wrapfn = enc ? CRYPTO_128_wrap_pad : CRYPTO_128_unwrap_pad;
91     else
92         wctx->wrapfn = enc ? CRYPTO_128_wrap : CRYPTO_128_unwrap;
93
94     if (iv != NULL) {
95         if (!ossl_cipher_generic_initiv(ctx, iv, ivlen))
96             return 0;
97     }
98     if (key != NULL) {
99         int use_forward_transform;
100
101         if (keylen != ctx->keylen) {
102            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
103            return 0;
104         }
105         /*
106          * See SP800-38F : Section 5.1
107          * The forward and inverse transformations for the AES block
108          * cipher—called “cipher” and “inverse  cipher” are informally known as
109          * the AES encryption and AES decryption functions, respectively.
110          * If the designated cipher function for a key-wrap algorithm is chosen
111          * to be the AES decryption function, then CIPH-1K will be the AES
112          * encryption function.
113          */
114         if ((ctx->flags & EVP_CIPH_FLAG_INVERSE_CIPHER) == 0)
115             use_forward_transform = ctx->enc;
116         else
117             use_forward_transform = !ctx->enc;
118         if (use_forward_transform) {
119             AES_set_encrypt_key(key, keylen * 8, &wctx->ks.ks);
120             ctx->block = (block128_f)AES_encrypt;
121         } else {
122             AES_set_decrypt_key(key, keylen * 8, &wctx->ks.ks);
123             ctx->block = (block128_f)AES_decrypt;
124         }
125     }
126     return 1;
127 }
128
129 static int aes_wrap_einit(void *ctx, const unsigned char *key, size_t keylen,
130                           const unsigned char *iv, size_t ivlen)
131 {
132     return aes_wrap_init(ctx, key, keylen, iv, ivlen, 1);
133 }
134
135 static int aes_wrap_dinit(void *ctx, const unsigned char *key, size_t keylen,
136                           const unsigned char *iv, size_t ivlen)
137 {
138     return aes_wrap_init(ctx, key, keylen, iv, ivlen, 0);
139 }
140
141 static int aes_wrap_cipher_internal(void *vctx, unsigned char *out,
142                                     const unsigned char *in, size_t inlen)
143 {
144     PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
145     PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx;
146     size_t rv;
147     int pad = ctx->pad;
148
149     /* No final operation so always return zero length */
150     if (in == NULL)
151         return 0;
152
153     /* Input length must always be non-zero */
154     if (inlen == 0)
155         return -1;
156
157     /* If decrypting need at least 16 bytes and multiple of 8 */
158     if (!ctx->enc && (inlen < 16 || inlen & 0x7))
159         return -1;
160
161     /* If not padding input must be multiple of 8 */
162     if (!pad && inlen & 0x7)
163         return -1;
164
165     if (out == NULL) {
166         if (ctx->enc) {
167             /* If padding round up to multiple of 8 */
168             if (pad)
169                 inlen = (inlen + 7) / 8 * 8;
170             /* 8 byte prefix */
171             return inlen + 8;
172         } else {
173             /*
174              * If not padding output will be exactly 8 bytes smaller than
175              * input. If padding it will be at least 8 bytes smaller but we
176              * don't know how much.
177              */
178             return inlen - 8;
179         }
180     }
181
182     rv = wctx->wrapfn(&wctx->ks.ks, ctx->iv_set ? ctx->iv : NULL, out, in,
183                       inlen, ctx->block);
184     return rv ? (int)rv : -1;
185 }
186
187 static int aes_wrap_final(void *vctx, unsigned char *out, size_t *outl,
188                           size_t outsize)
189 {
190     if (!ossl_prov_is_running())
191         return 0;
192
193     *outl = 0;
194     return 1;
195 }
196
197 static int aes_wrap_cipher(void *vctx,
198                            unsigned char *out, size_t *outl, size_t outsize,
199                            const unsigned char *in, size_t inl)
200 {
201     PROV_AES_WRAP_CTX *ctx = (PROV_AES_WRAP_CTX *)vctx;
202     size_t len;
203
204     if (!ossl_prov_is_running())
205         return 0;
206
207     if (inl == 0) {
208         *outl = 0;
209         return 1;
210     }
211
212     if (outsize < inl) {
213         ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
214         return -1;
215     }
216
217     len = aes_wrap_cipher_internal(ctx, out, in, inl);
218     if (len == 0)
219         return -1;
220
221     *outl = len;
222     return 1;
223 }
224
225 static int aes_wrap_set_ctx_params(void *vctx, const OSSL_PARAM params[])
226 {
227     PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
228     const OSSL_PARAM *p;
229     size_t keylen = 0;
230
231     p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
232     if (p != NULL) {
233         if (!OSSL_PARAM_get_size_t(p, &keylen)) {
234             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
235             return 0;
236         }
237         if (ctx->keylen != keylen) {
238             ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
239             return 0;
240         }
241     }
242     return 1;
243 }
244
245 #define IMPLEMENT_cipher(mode, fname, UCMODE, flags, kbits, blkbits, ivbits)   \
246     static OSSL_FUNC_cipher_get_params_fn aes_##kbits##_##fname##_get_params;  \
247     static int aes_##kbits##_##fname##_get_params(OSSL_PARAM params[])         \
248     {                                                                          \
249         return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE,\
250                                               flags, kbits, blkbits, ivbits);  \
251     }                                                                          \
252     static OSSL_FUNC_cipher_newctx_fn aes_##kbits##fname##_newctx;             \
253     static void *aes_##kbits##fname##_newctx(void *provctx)                    \
254     {                                                                          \
255         return aes_##mode##_newctx(kbits, blkbits, ivbits,                     \
256                                    EVP_CIPH_##UCMODE##_MODE, flags);           \
257     }                                                                          \
258     const OSSL_DISPATCH ossl_##aes##kbits##fname##_functions[] = {             \
259         { OSSL_FUNC_CIPHER_NEWCTX,                                             \
260             (void (*)(void))aes_##kbits##fname##_newctx },                     \
261         { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_##mode##_einit }, \
262         { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_##mode##_dinit }, \
263         { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_##mode##_cipher },      \
264         { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_##mode##_final },        \
265         { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_##mode##_freectx },    \
266         { OSSL_FUNC_CIPHER_GET_PARAMS,                                         \
267             (void (*)(void))aes_##kbits##_##fname##_get_params },              \
268         { OSSL_FUNC_CIPHER_GETTABLE_PARAMS,                                    \
269             (void (*)(void))ossl_cipher_generic_gettable_params },             \
270         { OSSL_FUNC_CIPHER_GET_CTX_PARAMS,                                     \
271             (void (*)(void))ossl_cipher_generic_get_ctx_params },              \
272         { OSSL_FUNC_CIPHER_SET_CTX_PARAMS,                                     \
273             (void (*)(void))aes_wrap_set_ctx_params },                         \
274         { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS,                                \
275             (void (*)(void))ossl_cipher_generic_gettable_ctx_params },         \
276         { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,                                \
277             (void (*)(void))ossl_cipher_generic_settable_ctx_params },         \
278         { 0, NULL }                                                            \
279     }
280
281 IMPLEMENT_cipher(wrap, wrap, WRAP, WRAP_FLAGS, 256, 64, AES_WRAP_NOPAD_IVLEN * 8);
282 IMPLEMENT_cipher(wrap, wrap, WRAP, WRAP_FLAGS, 192, 64, AES_WRAP_NOPAD_IVLEN * 8);
283 IMPLEMENT_cipher(wrap, wrap, WRAP, WRAP_FLAGS, 128, 64, AES_WRAP_NOPAD_IVLEN * 8);
284 IMPLEMENT_cipher(wrap, wrappad, WRAP, WRAP_FLAGS, 256, 64, AES_WRAP_PAD_IVLEN * 8);
285 IMPLEMENT_cipher(wrap, wrappad, WRAP, WRAP_FLAGS, 192, 64, AES_WRAP_PAD_IVLEN * 8);
286 IMPLEMENT_cipher(wrap, wrappad, WRAP, WRAP_FLAGS, 128, 64, AES_WRAP_PAD_IVLEN * 8);
287
288 IMPLEMENT_cipher(wrap, wrapinv, WRAP, WRAP_FLAGS_INV, 256, 64, AES_WRAP_NOPAD_IVLEN * 8);
289 IMPLEMENT_cipher(wrap, wrapinv, WRAP, WRAP_FLAGS_INV, 192, 64, AES_WRAP_NOPAD_IVLEN * 8);
290 IMPLEMENT_cipher(wrap, wrapinv, WRAP, WRAP_FLAGS_INV, 128, 64, AES_WRAP_NOPAD_IVLEN * 8);
291 IMPLEMENT_cipher(wrap, wrappadinv, WRAP, WRAP_FLAGS_INV, 256, 64, AES_WRAP_PAD_IVLEN * 8);
292 IMPLEMENT_cipher(wrap, wrappadinv, WRAP, WRAP_FLAGS_INV, 192, 64, AES_WRAP_PAD_IVLEN * 8);
293 IMPLEMENT_cipher(wrap, wrappadinv, WRAP, WRAP_FLAGS_INV, 128, 64, AES_WRAP_PAD_IVLEN * 8);