Add aes_ccm to provider
[openssl.git] / providers / common / ciphers / ccm_hw.c
1 /*
2  * Copyright 2019 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 #include <openssl/opensslconf.h>
11 #include "ciphers_locl.h"
12 #include "internal/aes_platform.h"
13
14 #define AES_CCM_SET_KEY_FN(fn_set_enc_key, fn_blk, fn_ccm_enc, fn_ccm_dec)     \
15     fn_set_enc_key(key, keylen * 8, &actx->ccm.ks.ks);                         \
16     CRYPTO_ccm128_init(&ctx->ccm_ctx, ctx->m, ctx->l, &actx->ccm.ks.ks,        \
17                        (block128_f)fn_blk);                                    \
18     ctx->str = ctx->enc ? (ccm128_f)fn_ccm_enc : (ccm128_f)fn_ccm_dec;         \
19     ctx->key_set = 1;
20
21 static int ccm_generic_aes_init_key(PROV_CCM_CTX *ctx,
22                                     const unsigned char *key, size_t keylen)
23 {
24     PROV_AES_CCM_CTX *actx = (PROV_AES_CCM_CTX *)ctx;
25
26 #ifdef HWAES_CAPABLE
27     if (HWAES_CAPABLE) {
28         AES_CCM_SET_KEY_FN(HWAES_set_encrypt_key, HWAES_encrypt, NULL, NULL);
29     } else
30 #endif /* HWAES_CAPABLE */
31 #ifdef VPAES_CAPABLE
32     if (VPAES_CAPABLE) {
33         AES_CCM_SET_KEY_FN(vpaes_set_encrypt_key, vpaes_encrypt, NULL, NULL);
34     } else
35 #endif
36     {
37         AES_CCM_SET_KEY_FN(AES_set_encrypt_key, AES_encrypt, NULL, NULL)
38     }
39     return 1;
40 }
41
42 static int ccm_generic_setiv(PROV_CCM_CTX *ctx, const unsigned char *nonce,
43                              size_t nlen, size_t mlen)
44 {
45     return CRYPTO_ccm128_setiv(&ctx->ccm_ctx, nonce, nlen, mlen) == 0;
46 }
47
48 static int ccm_generic_setaad(PROV_CCM_CTX *ctx, const unsigned char *aad,
49                               size_t alen)
50 {
51     CRYPTO_ccm128_aad(&ctx->ccm_ctx, aad, alen);
52     return 1;
53 }
54
55 static int ccm_generic_gettag(PROV_CCM_CTX *ctx, unsigned char *tag,
56                               size_t tlen)
57 {
58     return CRYPTO_ccm128_tag(&ctx->ccm_ctx, tag, tlen) > 0;
59 }
60
61 static int ccm_generic_auth_encrypt(PROV_CCM_CTX *ctx, const unsigned char *in,
62                                     unsigned char *out, size_t len,
63                                     unsigned char *tag, size_t taglen)
64 {
65     int rv;
66
67     if (ctx->str != NULL)
68         rv = CRYPTO_ccm128_encrypt_ccm64(&ctx->ccm_ctx, in,
69                                          out, len, ctx->str) == 0;
70     else
71         rv = CRYPTO_ccm128_encrypt(&ctx->ccm_ctx, in, out, len) == 0;
72
73     if (rv == 1 && tag != NULL)
74         rv = (CRYPTO_ccm128_tag(&ctx->ccm_ctx, tag, taglen) > 0);
75     return rv;
76 }
77
78 static int ccm_generic_auth_decrypt(PROV_CCM_CTX *ctx, const unsigned char *in,
79                                     unsigned char *out, size_t len,
80                                     unsigned char *expected_tag,
81                                     size_t taglen)
82 {
83     int rv = 0;
84
85     if (ctx->str != NULL)
86         rv = CRYPTO_ccm128_decrypt_ccm64(&ctx->ccm_ctx, in, out, len,
87                                          ctx->str) == 0;
88     else
89         rv = CRYPTO_ccm128_decrypt(&ctx->ccm_ctx, in, out, len) == 0;
90     if (rv) {
91         unsigned char tag[16];
92
93         if (!CRYPTO_ccm128_tag(&ctx->ccm_ctx, tag, taglen)
94             || CRYPTO_memcmp(tag, expected_tag, taglen) != 0)
95             rv = 0;
96     }
97     if (rv == 0)
98         OPENSSL_cleanse(out, len);
99     return rv;
100 }
101
102 static const PROV_CCM_HW aes_ccm = {
103     ccm_generic_aes_init_key,
104     ccm_generic_setiv,
105     ccm_generic_setaad,
106     ccm_generic_auth_encrypt,
107     ccm_generic_auth_decrypt,
108     ccm_generic_gettag
109 };
110
111 #if defined(S390X_aes_128_CAPABLE)
112 # include "aes_ccm_s390x.c"
113 #elif defined(AESNI_CAPABLE)
114
115 /* AES-NI section */
116 static int ccm_aesni_init_key(PROV_CCM_CTX *ctx,
117                               const unsigned char *key, size_t keylen)
118 {
119     PROV_AES_CCM_CTX *actx = (PROV_AES_CCM_CTX *)ctx;
120
121     AES_CCM_SET_KEY_FN(aesni_set_encrypt_key, aesni_encrypt,
122                        aesni_ccm64_encrypt_blocks, aesni_ccm64_decrypt_blocks);
123     return 1;
124 }
125
126 static const PROV_CCM_HW aesni_ccm = {
127     ccm_aesni_init_key,
128     ccm_generic_setiv,
129     ccm_generic_setaad,
130     ccm_generic_auth_encrypt,
131     ccm_generic_auth_decrypt,
132     ccm_generic_gettag
133 };
134
135 const PROV_CCM_HW *PROV_AES_HW_ccm(size_t keybits)
136 {
137     return AESNI_CAPABLE ? &aesni_ccm : &aes_ccm;
138 }
139
140 #elif defined(SPARC_AES_CAPABLE)
141 /* Fujitsu SPARC64 X support */
142 static int ccm_t4_aes_init_key(PROV_CCM_CTX *ctx,
143                                const unsigned char *key, size_t keylen)
144 {
145     PROV_AES_CCM_CTX *actx = (PROV_AES_CCM_CTX *)ctx;
146
147     AES_CCM_SET_KEY_FN(aes_t4_set_encrypt_key, aes_t4_encrypt, NULL, NULL);
148     return 1;
149 }
150
151 static const PROV_CCM_HW t4_aes_ccm = {
152     ccm_t4_aes_init_key,
153     ccm_generic_setiv,
154     ccm_generic_setaad,
155     ccm_generic_auth_encrypt,
156     ccm_generic_auth_decrypt,
157     ccm_generic_gettag
158 };
159
160 const PROV_CCM_HW *PROV_AES_HW_ccm(size_t keybits)
161 {
162     return SPARC_AES_CAPABLE ? &t4_aes_ccm : &aes_ccm;
163 }
164
165 #else
166 const PROV_CCM_HW *PROV_AES_HW_ccm(size_t keybits)
167 {
168     return &aes_ccm;
169 }
170 #endif
171
172 #if !defined(OPENSSL_NO_ARIA) && !defined(FIPS_MODE)
173 /* ARIA CCM Algorithm specific methods */
174 static int ccm_aria_init_key(PROV_CCM_CTX *ctx,
175                              const unsigned char *key, size_t keylen)
176 {
177     PROV_ARIA_CCM_CTX *actx = (PROV_ARIA_CCM_CTX *)ctx;
178
179     aria_set_encrypt_key(key, keylen * 8, &actx->ks.ks);
180     CRYPTO_ccm128_init(&ctx->ccm_ctx, ctx->m, ctx->l, &actx->ks.ks,
181                        (block128_f)aria_encrypt);
182     ctx->str = NULL;
183     ctx->key_set = 1;
184     return 1;
185 }
186
187 static const PROV_CCM_HW ccm_aria = {
188     ccm_aria_init_key,
189     ccm_generic_setiv,
190     ccm_generic_setaad,
191     ccm_generic_auth_encrypt,
192     ccm_generic_auth_decrypt,
193     ccm_generic_gettag
194 };
195 const PROV_CCM_HW *PROV_ARIA_HW_ccm(size_t keybits)
196 {
197     return &ccm_aria;
198 }
199 #endif /* OPENSSL_NO_ARIA */