Move the PROV_R reason codes to a public header
[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 <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
38 typedef struct prov_aes_wrap_ctx_st {
39     PROV_CIPHER_CTX base;
40     union {
41         OSSL_UNION_ALIGN;
42         AES_KEY ks;
43     } ks;
44     aeswrap_fn wrapfn;
45
46 } PROV_AES_WRAP_CTX;
47
48
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
68 static void aes_wrap_freectx(void *vctx)
69 {
70     PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx;
71
72     ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
73     OPENSSL_clear_free(wctx,  sizeof(*wctx));
74 }
75
76 static int aes_wrap_init(void *vctx, const unsigned char *key,
77                          size_t keylen, const unsigned char *iv,
78                          size_t ivlen, int enc)
79 {
80     PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
81     PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx;
82
83     if (!ossl_prov_is_running())
84         return 0;
85
86     ctx->enc = enc;
87     if (ctx->pad)
88         wctx->wrapfn = enc ? CRYPTO_128_wrap_pad : CRYPTO_128_unwrap_pad;
89     else
90         wctx->wrapfn = enc ? CRYPTO_128_wrap : CRYPTO_128_unwrap;
91
92     if (iv != NULL) {
93         if (!ossl_cipher_generic_initiv(ctx, iv, ivlen))
94             return 0;
95     }
96     if (key != NULL) {
97         int use_forward_transform;
98
99         if (keylen != ctx->keylen) {
100            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
101            return 0;
102         }
103         /*
104          * See SP800-38F : Section 5.1
105          * The forward and inverse transformations for the AES block
106          * cipher—called “cipher” and “inverse  cipher” are informally known as
107          * the AES encryption and AES decryption functions, respectively.
108          * If the designated cipher function for a key-wrap algorithm is chosen
109          * to be the AES decryption function, then CIPH-1K will be the AES
110          * encryption function.
111          */
112         if (ctx->inverse_cipher == 0)
113             use_forward_transform = ctx->enc;
114         else
115             use_forward_transform = !ctx->enc;
116         if (use_forward_transform) {
117             AES_set_encrypt_key(key, keylen * 8, &wctx->ks.ks);
118             ctx->block = (block128_f)AES_encrypt;
119         } else {
120             AES_set_decrypt_key(key, keylen * 8, &wctx->ks.ks);
121             ctx->block = (block128_f)AES_decrypt;
122         }
123     }
124     return 1;
125 }
126
127 static int aes_wrap_einit(void *ctx, const unsigned char *key, size_t keylen,
128                           const unsigned char *iv, size_t ivlen)
129 {
130     return aes_wrap_init(ctx, key, keylen, iv, ivlen, 1);
131 }
132
133 static int aes_wrap_dinit(void *ctx, const unsigned char *key, size_t keylen,
134                           const unsigned char *iv, size_t ivlen)
135 {
136     return aes_wrap_init(ctx, key, keylen, iv, ivlen, 0);
137 }
138
139 static int aes_wrap_cipher_internal(void *vctx, unsigned char *out,
140                                     const unsigned char *in, size_t inlen)
141 {
142     PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
143     PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx;
144     size_t rv;
145     int pad = ctx->pad;
146
147     /* No final operation so always return zero length */
148     if (in == NULL)
149         return 0;
150
151     /* Input length must always be non-zero */
152     if (inlen == 0)
153         return -1;
154
155     /* If decrypting need at least 16 bytes and multiple of 8 */
156     if (!ctx->enc && (inlen < 16 || inlen & 0x7))
157         return -1;
158
159     /* If not padding input must be multiple of 8 */
160     if (!pad && inlen & 0x7)
161         return -1;
162
163     if (out == NULL) {
164         if (ctx->enc) {
165             /* If padding round up to multiple of 8 */
166             if (pad)
167                 inlen = (inlen + 7) / 8 * 8;
168             /* 8 byte prefix */
169             return inlen + 8;
170         } else {
171             /*
172              * If not padding output will be exactly 8 bytes smaller than
173              * input. If padding it will be at least 8 bytes smaller but we
174              * don't know how much.
175              */
176             return inlen - 8;
177         }
178     }
179
180     rv = wctx->wrapfn(&wctx->ks.ks, ctx->iv_set ? ctx->iv : NULL, out, in,
181                       inlen, ctx->block);
182     return rv ? (int)rv : -1;
183 }
184
185 static int aes_wrap_final(void *vctx, unsigned char *out, size_t *outl,
186                           size_t outsize)
187 {
188     if (!ossl_prov_is_running())
189         return 0;
190
191     *outl = 0;
192     return 1;
193 }
194
195 static int aes_wrap_cipher(void *vctx,
196                            unsigned char *out, size_t *outl, size_t outsize,
197                            const unsigned char *in, size_t inl)
198 {
199     PROV_AES_WRAP_CTX *ctx = (PROV_AES_WRAP_CTX *)vctx;
200     size_t len;
201
202     if (!ossl_prov_is_running())
203         return 0;
204
205     if (inl == 0) {
206         *outl = 0;
207         return 1;
208     }
209
210     if (outsize < inl) {
211         ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
212         return -1;
213     }
214
215     len = aes_wrap_cipher_internal(ctx, out, in, inl);
216     if (len == 0)
217         return -1;
218
219     *outl = len;
220     return 1;
221 }
222
223 static int aes_wrap_set_ctx_params(void *vctx, const OSSL_PARAM params[])
224 {
225     PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
226     const OSSL_PARAM *p;
227     size_t keylen = 0;
228
229     p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
230     if (p != NULL) {
231         if (!OSSL_PARAM_get_size_t(p, &keylen)) {
232             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
233             return 0;
234         }
235         if (ctx->keylen != keylen) {
236             ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
237             return 0;
238         }
239     }
240     return 1;
241 }
242
243 #define IMPLEMENT_cipher(mode, fname, UCMODE, flags, kbits, blkbits, ivbits)   \
244     static OSSL_FUNC_cipher_get_params_fn aes_##kbits##_##fname##_get_params;  \
245     static int aes_##kbits##_##fname##_get_params(OSSL_PARAM params[])         \
246     {                                                                          \
247         return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE,\
248                                               flags, kbits, blkbits, ivbits);  \
249     }                                                                          \
250     static OSSL_FUNC_cipher_newctx_fn aes_##kbits##fname##_newctx;             \
251     static void *aes_##kbits##fname##_newctx(void *provctx)                    \
252     {                                                                          \
253         return aes_##mode##_newctx(kbits, blkbits, ivbits,                     \
254                                    EVP_CIPH_##UCMODE##_MODE, flags);           \
255     }                                                                          \
256     const OSSL_DISPATCH ossl_##aes##kbits##fname##_functions[] = {             \
257         { OSSL_FUNC_CIPHER_NEWCTX,                                             \
258             (void (*)(void))aes_##kbits##fname##_newctx },                     \
259         { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_##mode##_einit }, \
260         { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_##mode##_dinit }, \
261         { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_##mode##_cipher },      \
262         { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_##mode##_final },        \
263         { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_##mode##_freectx },    \
264         { OSSL_FUNC_CIPHER_GET_PARAMS,                                         \
265             (void (*)(void))aes_##kbits##_##fname##_get_params },              \
266         { OSSL_FUNC_CIPHER_GETTABLE_PARAMS,                                    \
267             (void (*)(void))ossl_cipher_generic_gettable_params },             \
268         { OSSL_FUNC_CIPHER_GET_CTX_PARAMS,                                     \
269             (void (*)(void))ossl_cipher_generic_get_ctx_params },              \
270         { OSSL_FUNC_CIPHER_SET_CTX_PARAMS,                                     \
271             (void (*)(void))aes_wrap_set_ctx_params },                         \
272         { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS,                                \
273             (void (*)(void))ossl_cipher_generic_gettable_ctx_params },         \
274         { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,                                \
275             (void (*)(void))ossl_cipher_generic_settable_ctx_params },         \
276         { 0, NULL }                                                            \
277     }
278
279 IMPLEMENT_cipher(wrap, wrap, WRAP, WRAP_FLAGS, 256, 64, AES_WRAP_NOPAD_IVLEN * 8);
280 IMPLEMENT_cipher(wrap, wrap, WRAP, WRAP_FLAGS, 192, 64, AES_WRAP_NOPAD_IVLEN * 8);
281 IMPLEMENT_cipher(wrap, wrap, WRAP, WRAP_FLAGS, 128, 64, AES_WRAP_NOPAD_IVLEN * 8);
282 IMPLEMENT_cipher(wrap, wrappad, WRAP, WRAP_FLAGS, 256, 64, AES_WRAP_PAD_IVLEN * 8);
283 IMPLEMENT_cipher(wrap, wrappad, WRAP, WRAP_FLAGS, 192, 64, AES_WRAP_PAD_IVLEN * 8);
284 IMPLEMENT_cipher(wrap, wrappad, WRAP, WRAP_FLAGS, 128, 64, AES_WRAP_PAD_IVLEN * 8);
285
286 IMPLEMENT_cipher(wrap, wrapinv, WRAP, WRAP_FLAGS_INV, 256, 64, AES_WRAP_NOPAD_IVLEN * 8);
287 IMPLEMENT_cipher(wrap, wrapinv, WRAP, WRAP_FLAGS_INV, 192, 64, AES_WRAP_NOPAD_IVLEN * 8);
288 IMPLEMENT_cipher(wrap, wrapinv, WRAP, WRAP_FLAGS_INV, 128, 64, AES_WRAP_NOPAD_IVLEN * 8);
289 IMPLEMENT_cipher(wrap, wrappadinv, WRAP, WRAP_FLAGS_INV, 256, 64, AES_WRAP_PAD_IVLEN * 8);
290 IMPLEMENT_cipher(wrap, wrappadinv, WRAP, WRAP_FLAGS_INV, 192, 64, AES_WRAP_PAD_IVLEN * 8);
291 IMPLEMENT_cipher(wrap, wrappadinv, WRAP, WRAP_FLAGS_INV, 128, 64, AES_WRAP_PAD_IVLEN * 8);