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 "prov/ciphercommon.h"
11#include "prov/ciphercommon_gcm.h"
12
13
14int gcm_setiv(PROV_GCM_CTX *ctx, const unsigned char *iv, size_t ivlen)
15{
16 CRYPTO_gcm128_setiv(&ctx->gcm, iv, ivlen);
17 return 1;
18}
19
20int gcm_aad_update(PROV_GCM_CTX *ctx, const unsigned char *aad, size_t aad_len)
21{
22 return CRYPTO_gcm128_aad(&ctx->gcm, aad, aad_len) == 0;
23}
24
25int gcm_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in,
26 size_t len, unsigned char *out)
27{
28 if (ctx->enc) {
29 if (ctx->ctr != NULL) {
30#if defined(AES_GCM_ASM)
31 size_t bulk = 0;
32
33 if (len >= 32 && AES_GCM_ASM(ctx)) {
34 size_t res = (16 - ctx->gcm.mres) % 16;
35
36 if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, res))
37 return 0;
38 bulk = aesni_gcm_encrypt(in + res, out + res, len - res,
39 ctx->gcm.key,
40 ctx->gcm.Yi.c, ctx->gcm.Xi.u);
41 ctx->gcm.len.u[1] += bulk;
42 bulk += res;
43 }
44 if (CRYPTO_gcm128_encrypt_ctr32(&ctx->gcm, in + bulk, out + bulk,
45 len - bulk, ctx->ctr))
46 return 0;
47#else
48 if (CRYPTO_gcm128_encrypt_ctr32(&ctx->gcm, in, out, len, ctx->ctr))
49 return 0;
50#endif /* AES_GCM_ASM */
51 } else {
52 if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, len))
53 return 0;
54 }
55 } else {
56 if (ctx->ctr != NULL) {
57#if defined(AES_GCM_ASM)
58 size_t bulk = 0;
59
60 if (len >= 16 && AES_GCM_ASM(ctx)) {
61 size_t res = (16 - ctx->gcm.mres) % 16;
62
63 if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, res))
64 return -1;
65
66 bulk = aesni_gcm_decrypt(in + res, out + res, len - res,
67 ctx->gcm.key,
68 ctx->gcm.Yi.c, ctx->gcm.Xi.u);
69 ctx->gcm.len.u[1] += bulk;
70 bulk += res;
71 }
72 if (CRYPTO_gcm128_decrypt_ctr32(&ctx->gcm, in + bulk, out + bulk,
73 len - bulk, ctx->ctr))
74 return 0;
75#else
76 if (CRYPTO_gcm128_decrypt_ctr32(&ctx->gcm, in, out, len, ctx->ctr))
77 return 0;
78#endif /* AES_GCM_ASM */
79 } else {
80 if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, len))
81 return 0;
82 }
83 }
84 return 1;
85}
86
87int gcm_cipher_final(PROV_GCM_CTX *ctx, unsigned char *tag)
88{
89 if (ctx->enc) {
90 CRYPTO_gcm128_tag(&ctx->gcm, tag, GCM_TAG_MAX_SIZE);
91 ctx->taglen = GCM_TAG_MAX_SIZE;
92 } else {
93 if (CRYPTO_gcm128_finish(&ctx->gcm, tag, ctx->taglen) != 0)
94 return 0;
95 }
96 return 1;
97}
98
99int gcm_one_shot(PROV_GCM_CTX *ctx, unsigned char *aad, size_t aad_len,
100 const unsigned char *in, size_t in_len,
101 unsigned char *out, unsigned char *tag, size_t tag_len)
102{
103 int ret = 0;
104
105 /* Use saved AAD */
106 if (!ctx->hw->aadupdate(ctx, aad, aad_len))
107 goto err;
108 if (!ctx->hw->cipherupdate(ctx, in, in_len, out))
109 goto err;
110 ctx->taglen = GCM_TAG_MAX_SIZE;
111 if (!ctx->hw->cipherfinal(ctx, tag))
112 goto err;
113 ret = 1;
114
115err:
116 return ret;
117}
118