Update copyright year
[openssl.git] / providers / implementations / ciphers / cipher_aes_gcm_hw.c
index 0eb799451d918b2fd867ea97e19a9bc974a7b021..c662887272bfb7960f9d8d46c14bd79539ee94e8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -17,7 +17,7 @@
 
 #include "cipher_aes_gcm.h"
 
-static int generic_aes_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
+static int aes_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
                                    size_t keylen)
 {
     PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
@@ -59,11 +59,76 @@ static int generic_aes_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
     return 1;
 }
 
+static int generic_aes_gcm_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in,
+                                         size_t len, unsigned char *out)
+{
+    if (ctx->enc) {
+        if (ctx->ctr != NULL) {
+#if defined(AES_GCM_ASM)
+            size_t bulk = 0;
+
+            if (len >= AES_GCM_ENC_BYTES && AES_GCM_ASM(ctx)) {
+                size_t res = (16 - ctx->gcm.mres) % 16;
+
+                if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, res))
+                    return 0;
+
+                bulk = AES_gcm_encrypt(in + res, out + res, len - res,
+                                       ctx->gcm.key,
+                                       ctx->gcm.Yi.c, ctx->gcm.Xi.u);
+
+                ctx->gcm.len.u[1] += bulk;
+                bulk += res;
+            }
+            if (CRYPTO_gcm128_encrypt_ctr32(&ctx->gcm, in + bulk, out + bulk,
+                                            len - bulk, ctx->ctr))
+                return 0;
+#else
+            if (CRYPTO_gcm128_encrypt_ctr32(&ctx->gcm, in, out, len, ctx->ctr))
+                return 0;
+#endif /* AES_GCM_ASM */
+        } else {
+            if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, len))
+                return 0;
+        }
+    } else {
+        if (ctx->ctr != NULL) {
+#if defined(AES_GCM_ASM)
+            size_t bulk = 0;
+
+            if (len >= AES_GCM_DEC_BYTES && AES_GCM_ASM(ctx)) {
+                size_t res = (16 - ctx->gcm.mres) % 16;
+
+                if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, res))
+                    return -1;
+
+                bulk = AES_gcm_decrypt(in + res, out + res, len - res,
+                                       ctx->gcm.key,
+                                       ctx->gcm.Yi.c, ctx->gcm.Xi.u);
+
+                ctx->gcm.len.u[1] += bulk;
+                bulk += res;
+            }
+            if (CRYPTO_gcm128_decrypt_ctr32(&ctx->gcm, in + bulk, out + bulk,
+                                            len - bulk, ctx->ctr))
+                return 0;
+#else
+            if (CRYPTO_gcm128_decrypt_ctr32(&ctx->gcm, in, out, len, ctx->ctr))
+                return 0;
+#endif /* AES_GCM_ASM */
+        } else {
+            if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, len))
+                return 0;
+        }
+    }
+    return 1;
+}
+
 static const PROV_GCM_HW aes_gcm = {
-    generic_aes_gcm_initkey,
+    aes_gcm_initkey,
     gcm_setiv,
     gcm_aad_update,
-    gcm_cipher_update,
+    generic_aes_gcm_cipher_update,
     gcm_cipher_final,
     gcm_one_shot
 };