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 | |
14 | int 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 | |
20 | int 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 | |
25 | int 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 | |
87 | int 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 | |
99 | int 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 | |
115 | err: |
116 | return ret; |
117 | } |
118 | |