]> git.ipfire.org Git - thirdparty/openssl.git/blob - providers/common/ciphers/cipher_gcm_hw.c
Add basic aria and camellia ciphers modes to default provider
[thirdparty/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"