Add basic aria and camellia ciphers modes to default provider
[openssl.git] / providers / common / ciphers / cipher_gcm_hw.c
1 /*
2  * Copyright 2001-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 "cipher_locl.h"
11
12 static const PROV_GCM_HW aes_gcm;
13
14 static int gcm_setiv(PROV_GCM_CTX *ctx, const unsigned char *iv, size_t ivlen);
15 static int gcm_aad_update(PROV_GCM_CTX *ctx, const unsigned char *aad,
16                           size_t aad_len);
17 static int gcm_cipher_final(PROV_GCM_CTX *ctx, unsigned char *tag);
18 static int gcm_one_shot(PROV_GCM_CTX *ctx, unsigned char *aad, size_t aad_len,
19                         const unsigned char *in, size_t in_len,
20                         unsigned char *out, unsigned char *tag, size_t tag_len);
21 static int gcm_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in,
22                              size_t len, unsigned char *out);
23
24 #define SET_KEY_CTR_FN(ks, fn_set_enc_key, fn_block, fn_ctr)                   \
25     ctx->ks = ks;                                                              \
26     fn_set_enc_key(key, keylen * 8, ks);                                       \
27     CRYPTO_gcm128_init(&ctx->gcm, ks, (block128_f)fn_block);                   \
28     ctx->ctr = (ctr128_f)fn_ctr;                                               \
29     ctx->key_set = 1;
30
31 #if defined(AESNI_CAPABLE)
32 # include "cipher_aes_gcm_hw_aesni.inc"
33 #elif defined(AES_ASM) && (defined(__sparc) || defined(__sparc__))
34 # include "cipher_aes_gcm_hw_t4.inc"
35 #elif defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
36 # include "cipher_aes_gcm_hw_s390x.inc"
37 #else
38 const PROV_GCM_HW *PROV_AES_HW_gcm(size_t keybits)
39 {
40     return &aes_gcm;
41 }
42 #endif
43
44 static int generic_aes_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
45                                    size_t keylen)
46 {
47     PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
48     AES_KEY *ks = &actx->ks.ks;
49
50 # ifdef HWAES_CAPABLE
51     if (HWAES_CAPABLE) {
52 #  ifdef HWAES_ctr32_encrypt_blocks
53         SET_KEY_CTR_FN(ks, HWAES_set_encrypt_key, HWAES_encrypt,
54                        HWAES_ctr32_encrypt_blocks);
55 #  else
56         SET_KEY_CTR_FN(ks, HWAES_set_encrypt_key, HWAES_encrypt, NULL);
57 #  endif /* HWAES_ctr32_encrypt_blocks */
58     } else
59 # endif /* HWAES_CAPABLE */
60
61 # ifdef BSAES_CAPABLE
62     if (BSAES_CAPABLE) {
63         SET_KEY_CTR_FN(ks, AES_set_encrypt_key, AES_encrypt,
64                        bsaes_ctr32_encrypt_blocks);
65     } else
66 # endif /* BSAES_CAPABLE */
67
68 # ifdef VPAES_CAPABLE
69     if (VPAES_CAPABLE) {
70         SET_KEY_CTR_FN(ks, vpaes_set_encrypt_key, vpaes_encrypt, NULL);
71     } else
72 # endif /* VPAES_CAPABLE */
73
74     {
75 # ifdef AES_CTR_ASM
76         SET_KEY_CTR_FN(ks, AES_set_encrypt_key, AES_encrypt, AES_ctr32_encrypt);
77 # else
78         SET_KEY_CTR_FN(ks, AES_set_encrypt_key, AES_encrypt, NULL);
79 # endif /* AES_CTR_ASM */
80     }
81     ctx->key_set = 1;
82     return 1;
83 }
84
85 static int gcm_setiv(PROV_GCM_CTX *ctx, const unsigned char *iv, size_t ivlen)
86 {
87     CRYPTO_gcm128_setiv(&ctx->gcm, iv, ivlen);
88     return 1;
89 }
90
91 static int gcm_aad_update(PROV_GCM_CTX *ctx,
92                           const unsigned char *aad, size_t aad_len)
93 {
94     return CRYPTO_gcm128_aad(&ctx->gcm, aad, aad_len) == 0;
95 }
96
97 static int gcm_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in,
98                              size_t len, unsigned char *out)
99 {
100     if (ctx->enc) {
101         if (ctx->ctr != NULL) {
102 #if defined(AES_GCM_ASM)
103             size_t bulk = 0;
104
105             if (len >= 32 && AES_GCM_ASM(ctx)) {
106                 size_t res = (16 - ctx->gcm.mres) % 16;
107
108                 if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, res))
109                     return 0;
110                 bulk = aesni_gcm_encrypt(in + res, out + res, len - res,
111                                          ctx->gcm.key,
112                                          ctx->gcm.Yi.c, ctx->gcm.Xi.u);
113                 ctx->gcm.len.u[1] += bulk;
114                 bulk += res;
115             }
116             if (CRYPTO_gcm128_encrypt_ctr32(&ctx->gcm, in + bulk, out + bulk,
117                                             len - bulk, ctx->ctr))
118                 return 0;
119 #else
120             if (CRYPTO_gcm128_encrypt_ctr32(&ctx->gcm, in, out, len, ctx->ctr))
121                 return 0;
122 #endif /* AES_GCM_ASM */
123         } else {
124             if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, len))
125                 return 0;
126         }
127     } else {
128         if (ctx->ctr != NULL) {
129 #if defined(AES_GCM_ASM)
130             size_t bulk = 0;
131
132             if (len >= 16 && AES_GCM_ASM(ctx)) {
133                 size_t res = (16 - ctx->gcm.mres) % 16;
134
135                 if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, res))
136                     return -1;
137
138                 bulk = aesni_gcm_decrypt(in + res, out + res, len - res,
139                                          ctx->gcm.key,
140                                          ctx->gcm.Yi.c, ctx->gcm.Xi.u);
141                 ctx->gcm.len.u[1] += bulk;
142                 bulk += res;
143             }
144             if (CRYPTO_gcm128_decrypt_ctr32(&ctx->gcm, in + bulk, out + bulk,
145                                             len - bulk, ctx->ctr))
146                 return 0;
147 #else
148             if (CRYPTO_gcm128_decrypt_ctr32(&ctx->gcm, in, out, len, ctx->ctr))
149                 return 0;
150 #endif /* AES_GCM_ASM */
151         } else {
152             if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, len))
153                 return 0;
154         }
155     }
156     return 1;
157 }
158
159 static int gcm_cipher_final(PROV_GCM_CTX *ctx, unsigned char *tag)
160 {
161     if (ctx->enc) {
162         CRYPTO_gcm128_tag(&ctx->gcm, tag, GCM_TAG_MAX_SIZE);
163         ctx->taglen = GCM_TAG_MAX_SIZE;
164     } else {
165         if (ctx->taglen < 0
166             || CRYPTO_gcm128_finish(&ctx->gcm, tag, ctx->taglen) != 0)
167             return 0;
168     }
169     return 1;
170 }
171
172 static int gcm_one_shot(PROV_GCM_CTX *ctx, unsigned char *aad, size_t aad_len,
173                         const unsigned char *in, size_t in_len,
174                         unsigned char *out, unsigned char *tag, size_t tag_len)
175 {
176     int ret = 0;
177
178     /* Use saved AAD */
179     if (!ctx->hw->aadupdate(ctx, aad, aad_len))
180         goto err;
181     if (!ctx->hw->cipherupdate(ctx, in, in_len, out))
182         goto err;
183     ctx->taglen = GCM_TAG_MAX_SIZE;
184     if (!ctx->hw->cipherfinal(ctx, tag))
185         goto err;
186     ret = 1;
187
188 err:
189     return ret;
190 }
191
192 static const PROV_GCM_HW aes_gcm = {
193     generic_aes_gcm_initkey,
194     gcm_setiv,
195     gcm_aad_update,
196     gcm_cipher_update,
197     gcm_cipher_final,
198     gcm_one_shot
199 };
200
201 #include "cipher_aria_gcm_hw.inc"