xref: /src/crypto/openssl/providers/implementations/ciphers/cipher_aes_wrp.c (revision f25b8c9fb4f58cf61adb47d7570abe7caa6d385d)
1 /*
2  * Copyright 2019-2023 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 <openssl/proverr.h>
17 #include "cipher_aes.h"
18 #include "prov/providercommon.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 #define WRAP_FLAGS (PROV_CIPHER_FLAG_CUSTOM_IV)
26 #define WRAP_FLAGS_INV (WRAP_FLAGS | PROV_CIPHER_FLAG_INVERSE_CIPHER)
27 
28 typedef size_t (*aeswrap_fn)(void *key, const unsigned char *iv,
29     unsigned char *out, const unsigned char *in,
30     size_t inlen, block128_f block);
31 
32 static OSSL_FUNC_cipher_encrypt_init_fn aes_wrap_einit;
33 static OSSL_FUNC_cipher_decrypt_init_fn aes_wrap_dinit;
34 static OSSL_FUNC_cipher_update_fn aes_wrap_cipher;
35 static OSSL_FUNC_cipher_final_fn aes_wrap_final;
36 static OSSL_FUNC_cipher_freectx_fn aes_wrap_freectx;
37 static OSSL_FUNC_cipher_set_ctx_params_fn aes_wrap_set_ctx_params;
38 
39 typedef struct prov_aes_wrap_ctx_st {
40     PROV_CIPHER_CTX base;
41     union {
42         OSSL_UNION_ALIGN;
43         AES_KEY ks;
44     } ks;
45     aeswrap_fn wrapfn;
46 
47 } PROV_AES_WRAP_CTX;
48 
aes_wrap_newctx(size_t kbits,size_t blkbits,size_t ivbits,unsigned int mode,uint64_t flags)49 static void *aes_wrap_newctx(size_t kbits, size_t blkbits,
50     size_t ivbits, unsigned int mode, uint64_t flags)
51 {
52     PROV_AES_WRAP_CTX *wctx;
53     PROV_CIPHER_CTX *ctx;
54 
55     if (!ossl_prov_is_running())
56         return NULL;
57 
58     wctx = OPENSSL_zalloc(sizeof(*wctx));
59     ctx = (PROV_CIPHER_CTX *)wctx;
60     if (ctx != NULL) {
61         ossl_cipher_generic_initkey(ctx, kbits, blkbits, ivbits, mode, flags,
62             NULL, NULL);
63         ctx->pad = (ctx->ivlen == AES_WRAP_PAD_IVLEN);
64     }
65     return wctx;
66 }
67 
aes_wrap_dupctx(void * wctx)68 static void *aes_wrap_dupctx(void *wctx)
69 {
70     PROV_AES_WRAP_CTX *ctx = wctx;
71     PROV_AES_WRAP_CTX *dctx = wctx;
72 
73     if (!ossl_prov_is_running())
74         return NULL;
75 
76     if (ctx == NULL)
77         return NULL;
78     dctx = OPENSSL_memdup(ctx, sizeof(*ctx));
79 
80     if (dctx != NULL && dctx->base.tlsmac != NULL && dctx->base.alloced) {
81         dctx->base.tlsmac = OPENSSL_memdup(dctx->base.tlsmac,
82             dctx->base.tlsmacsize);
83         if (dctx->base.tlsmac == NULL) {
84             OPENSSL_free(dctx);
85             dctx = NULL;
86         }
87     }
88     return dctx;
89 }
90 
aes_wrap_freectx(void * vctx)91 static void aes_wrap_freectx(void *vctx)
92 {
93     PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx;
94 
95     ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
96     OPENSSL_clear_free(wctx, sizeof(*wctx));
97 }
98 
aes_wrap_init(void * vctx,const unsigned char * key,size_t keylen,const unsigned char * iv,size_t ivlen,const OSSL_PARAM params[],int enc)99 static int aes_wrap_init(void *vctx, const unsigned char *key,
100     size_t keylen, const unsigned char *iv,
101     size_t ivlen, const OSSL_PARAM params[], int enc)
102 {
103     PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
104     PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx;
105 
106     if (!ossl_prov_is_running())
107         return 0;
108 
109     ctx->enc = enc;
110     if (ctx->pad)
111         wctx->wrapfn = enc ? CRYPTO_128_wrap_pad : CRYPTO_128_unwrap_pad;
112     else
113         wctx->wrapfn = enc ? CRYPTO_128_wrap : CRYPTO_128_unwrap;
114 
115     if (iv != NULL) {
116         if (!ossl_cipher_generic_initiv(ctx, iv, ivlen))
117             return 0;
118     }
119     if (key != NULL) {
120         int use_forward_transform;
121 
122         if (keylen != ctx->keylen) {
123             ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
124             return 0;
125         }
126         /*
127          * See SP800-38F : Section 5.1
128          * The forward and inverse transformations for the AES block
129          * cipher—called “cipher” and “inverse  cipher” are informally known as
130          * the AES encryption and AES decryption functions, respectively.
131          * If the designated cipher function for a key-wrap algorithm is chosen
132          * to be the AES decryption function, then CIPH-1K will be the AES
133          * encryption function.
134          */
135         if (ctx->inverse_cipher == 0)
136             use_forward_transform = ctx->enc;
137         else
138             use_forward_transform = !ctx->enc;
139         if (use_forward_transform) {
140             AES_set_encrypt_key(key, keylen * 8, &wctx->ks.ks);
141             ctx->block = (block128_f)AES_encrypt;
142         } else {
143             AES_set_decrypt_key(key, keylen * 8, &wctx->ks.ks);
144             ctx->block = (block128_f)AES_decrypt;
145         }
146     }
147     return aes_wrap_set_ctx_params(ctx, params);
148 }
149 
aes_wrap_einit(void * ctx,const unsigned char * key,size_t keylen,const unsigned char * iv,size_t ivlen,const OSSL_PARAM params[])150 static int aes_wrap_einit(void *ctx, const unsigned char *key, size_t keylen,
151     const unsigned char *iv, size_t ivlen,
152     const OSSL_PARAM params[])
153 {
154     return aes_wrap_init(ctx, key, keylen, iv, ivlen, params, 1);
155 }
156 
aes_wrap_dinit(void * ctx,const unsigned char * key,size_t keylen,const unsigned char * iv,size_t ivlen,const OSSL_PARAM params[])157 static int aes_wrap_dinit(void *ctx, const unsigned char *key, size_t keylen,
158     const unsigned char *iv, size_t ivlen,
159     const OSSL_PARAM params[])
160 {
161     return aes_wrap_init(ctx, key, keylen, iv, ivlen, params, 0);
162 }
163 
aes_wrap_cipher_internal(void * vctx,unsigned char * out,const unsigned char * in,size_t inlen)164 static int aes_wrap_cipher_internal(void *vctx, unsigned char *out,
165     const unsigned char *in, size_t inlen)
166 {
167     PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
168     PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx;
169     size_t rv;
170     int pad = ctx->pad;
171 
172     /* No final operation so always return zero length */
173     if (in == NULL)
174         return 0;
175 
176     /* Input length must always be non-zero */
177     if (inlen == 0) {
178         ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_INPUT_LENGTH);
179         return -1;
180     }
181 
182     /* If decrypting need at least 16 bytes and multiple of 8 */
183     if (!ctx->enc && (inlen < 16 || inlen & 0x7)) {
184         ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_INPUT_LENGTH);
185         return -1;
186     }
187 
188     /* If not padding input must be multiple of 8 */
189     if (!pad && inlen & 0x7) {
190         ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_INPUT_LENGTH);
191         return -1;
192     }
193 
194     if (out == NULL) {
195         if (ctx->enc) {
196             /* If padding round up to multiple of 8 */
197             if (pad)
198                 inlen = (inlen + 7) / 8 * 8;
199             /* 8 byte prefix */
200             return inlen + 8;
201         } else {
202             /*
203              * If not padding output will be exactly 8 bytes smaller than
204              * input. If padding it will be at least 8 bytes smaller but we
205              * don't know how much.
206              */
207             return inlen - 8;
208         }
209     }
210 
211     rv = wctx->wrapfn(&wctx->ks.ks, ctx->iv_set ? ctx->iv : NULL, out, in,
212         inlen, ctx->block);
213     if (!rv) {
214         ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
215         return -1;
216     }
217     if (rv > INT_MAX) {
218         ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_OUTPUT_LENGTH);
219         return -1;
220     }
221     return (int)rv;
222 }
223 
aes_wrap_final(void * vctx,unsigned char * out,size_t * outl,size_t outsize)224 static int aes_wrap_final(void *vctx, unsigned char *out, size_t *outl,
225     size_t outsize)
226 {
227     if (!ossl_prov_is_running())
228         return 0;
229 
230     *outl = 0;
231     return 1;
232 }
233 
aes_wrap_cipher(void * vctx,unsigned char * out,size_t * outl,size_t outsize,const unsigned char * in,size_t inl)234 static int aes_wrap_cipher(void *vctx,
235     unsigned char *out, size_t *outl, size_t outsize,
236     const unsigned char *in, size_t inl)
237 {
238     PROV_AES_WRAP_CTX *ctx = (PROV_AES_WRAP_CTX *)vctx;
239     size_t len;
240 
241     if (!ossl_prov_is_running())
242         return 0;
243 
244     if (inl == 0) {
245         *outl = 0;
246         return 1;
247     }
248 
249     if (outsize < inl) {
250         ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
251         return 0;
252     }
253 
254     len = aes_wrap_cipher_internal(ctx, out, in, inl);
255     if (len <= 0)
256         return 0;
257 
258     *outl = len;
259     return 1;
260 }
261 
aes_wrap_set_ctx_params(void * vctx,const OSSL_PARAM params[])262 static int aes_wrap_set_ctx_params(void *vctx, const OSSL_PARAM params[])
263 {
264     PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
265     const OSSL_PARAM *p;
266     size_t keylen = 0;
267 
268     if (ossl_param_is_empty(params))
269         return 1;
270 
271     p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
272     if (p != NULL) {
273         if (!OSSL_PARAM_get_size_t(p, &keylen)) {
274             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
275             return 0;
276         }
277         if (ctx->keylen != keylen) {
278             ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
279             return 0;
280         }
281     }
282     return 1;
283 }
284 
285 #define IMPLEMENT_cipher(mode, fname, UCMODE, flags, kbits, blkbits, ivbits)    \
286     static OSSL_FUNC_cipher_get_params_fn aes_##kbits##_##fname##_get_params;   \
287     static int aes_##kbits##_##fname##_get_params(OSSL_PARAM params[])          \
288     {                                                                           \
289         return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
290             flags, kbits, blkbits, ivbits);                                     \
291     }                                                                           \
292     static OSSL_FUNC_cipher_newctx_fn aes_##kbits##fname##_newctx;              \
293     static void *aes_##kbits##fname##_newctx(void *provctx)                     \
294     {                                                                           \
295         return aes_##mode##_newctx(kbits, blkbits, ivbits,                      \
296             EVP_CIPH_##UCMODE##_MODE, flags);                                   \
297     }                                                                           \
298     const OSSL_DISPATCH ossl_##aes##kbits##fname##_functions[] = {              \
299         { OSSL_FUNC_CIPHER_NEWCTX,                                              \
300             (void (*)(void))aes_##kbits##fname##_newctx },                      \
301         { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_##mode##_einit },  \
302         { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_##mode##_dinit },  \
303         { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_##mode##_cipher },       \
304         { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_##mode##_final },         \
305         { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_##mode##_freectx },     \
306         { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aes_##mode##_dupctx },       \
307         { OSSL_FUNC_CIPHER_GET_PARAMS,                                          \
308             (void (*)(void))aes_##kbits##_##fname##_get_params },               \
309         { OSSL_FUNC_CIPHER_GETTABLE_PARAMS,                                     \
310             (void (*)(void))ossl_cipher_generic_gettable_params },              \
311         { OSSL_FUNC_CIPHER_GET_CTX_PARAMS,                                      \
312             (void (*)(void))ossl_cipher_generic_get_ctx_params },               \
313         { OSSL_FUNC_CIPHER_SET_CTX_PARAMS,                                      \
314             (void (*)(void))aes_wrap_set_ctx_params },                          \
315         { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS,                                 \
316             (void (*)(void))ossl_cipher_generic_gettable_ctx_params },          \
317         { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,                                 \
318             (void (*)(void))ossl_cipher_generic_settable_ctx_params },          \
319         OSSL_DISPATCH_END                                                       \
320     }
321 
322 IMPLEMENT_cipher(wrap, wrap, WRAP, WRAP_FLAGS, 256, 64, AES_WRAP_NOPAD_IVLEN * 8);
323 IMPLEMENT_cipher(wrap, wrap, WRAP, WRAP_FLAGS, 192, 64, AES_WRAP_NOPAD_IVLEN * 8);
324 IMPLEMENT_cipher(wrap, wrap, WRAP, WRAP_FLAGS, 128, 64, AES_WRAP_NOPAD_IVLEN * 8);
325 IMPLEMENT_cipher(wrap, wrappad, WRAP, WRAP_FLAGS, 256, 64, AES_WRAP_PAD_IVLEN * 8);
326 IMPLEMENT_cipher(wrap, wrappad, WRAP, WRAP_FLAGS, 192, 64, AES_WRAP_PAD_IVLEN * 8);
327 IMPLEMENT_cipher(wrap, wrappad, WRAP, WRAP_FLAGS, 128, 64, AES_WRAP_PAD_IVLEN * 8);
328 
329 IMPLEMENT_cipher(wrap, wrapinv, WRAP, WRAP_FLAGS_INV, 256, 64, AES_WRAP_NOPAD_IVLEN * 8);
330 IMPLEMENT_cipher(wrap, wrapinv, WRAP, WRAP_FLAGS_INV, 192, 64, AES_WRAP_NOPAD_IVLEN * 8);
331 IMPLEMENT_cipher(wrap, wrapinv, WRAP, WRAP_FLAGS_INV, 128, 64, AES_WRAP_NOPAD_IVLEN * 8);
332 IMPLEMENT_cipher(wrap, wrappadinv, WRAP, WRAP_FLAGS_INV, 256, 64, AES_WRAP_PAD_IVLEN * 8);
333 IMPLEMENT_cipher(wrap, wrappadinv, WRAP, WRAP_FLAGS_INV, 192, 64, AES_WRAP_PAD_IVLEN * 8);
334 IMPLEMENT_cipher(wrap, wrappadinv, WRAP, WRAP_FLAGS_INV, 128, 64, AES_WRAP_PAD_IVLEN * 8);
335