Line data Source code
1 : /*
2 : * Copyright (C) 2011-2012 Free Software Foundation, Inc.
3 : * Copyright (C) 2018 Red Hat, Inc.
4 : *
5 : * Author: Nikos Mavrogiannopoulos
6 : *
7 : * This file is part of GnuTLS.
8 : *
9 : * The GnuTLS is free software; you can redistribute it and/or
10 : * modify it under the terms of the GNU Lesser General Public License
11 : * as published by the Free Software Foundation; either version 2.1 of
12 : * the License, or (at your option) any later version.
13 : *
14 : * This library is distributed in the hope that it will be useful, but
15 : * WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 : * Lesser General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU Lesser General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>
21 : *
22 : */
23 :
24 : /*
25 : * The following code is an implementation of the AES-128-CBC cipher
26 : * using intel's AES instruction set.
27 : */
28 :
29 : #include "errors.h"
30 : #include "gnutls_int.h"
31 : #include <gnutls/crypto.h>
32 : #include "errors.h"
33 : #include <aes-x86.h>
34 : #include <sha-x86.h>
35 : #include <x86-common.h>
36 :
37 : struct aes_ctx {
38 : AES_KEY expanded_key;
39 : uint8_t iv[16];
40 : int enc;
41 : };
42 :
43 : static int
44 0 : aes_cipher_init(gnutls_cipher_algorithm_t algorithm, void **_ctx, int enc)
45 : {
46 : /* we use key size to distinguish */
47 0 : if (algorithm != GNUTLS_CIPHER_AES_128_CBC
48 0 : && algorithm != GNUTLS_CIPHER_AES_192_CBC
49 0 : && algorithm != GNUTLS_CIPHER_AES_256_CBC)
50 : return GNUTLS_E_INVALID_REQUEST;
51 :
52 0 : *_ctx = gnutls_calloc(1, sizeof(struct aes_ctx));
53 0 : if (*_ctx == NULL) {
54 0 : gnutls_assert();
55 0 : return GNUTLS_E_MEMORY_ERROR;
56 : }
57 :
58 0 : ((struct aes_ctx *) (*_ctx))->enc = enc;
59 :
60 0 : return 0;
61 : }
62 :
63 : static int
64 0 : aes_ssse3_cipher_setkey(void *_ctx, const void *userkey, size_t keysize)
65 : {
66 0 : struct aes_ctx *ctx = _ctx;
67 0 : int ret;
68 :
69 0 : CHECK_AES_KEYSIZE(keysize);
70 :
71 0 : if (ctx->enc)
72 0 : ret =
73 0 : vpaes_set_encrypt_key(userkey, keysize * 8,
74 0 : ALIGN16(&ctx->expanded_key));
75 : else
76 0 : ret =
77 0 : vpaes_set_decrypt_key(userkey, keysize * 8,
78 0 : ALIGN16(&ctx->expanded_key));
79 :
80 0 : if (ret != 0)
81 0 : return gnutls_assert_val(GNUTLS_E_ENCRYPTION_FAILED);
82 :
83 : return 0;
84 : }
85 :
86 : static int
87 0 : aes_ssse3_encrypt(void *_ctx, const void *src, size_t src_size,
88 : void *dst, size_t dst_size)
89 : {
90 0 : struct aes_ctx *ctx = _ctx;
91 :
92 0 : if (unlikely(src_size % 16 != 0))
93 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
94 :
95 0 : vpaes_cbc_encrypt(src, dst, src_size, ALIGN16(&ctx->expanded_key),
96 0 : ctx->iv, 1);
97 0 : return 0;
98 : }
99 :
100 : static int
101 0 : aes_ssse3_decrypt(void *_ctx, const void *src, size_t src_size,
102 : void *dst, size_t dst_size)
103 : {
104 0 : struct aes_ctx *ctx = _ctx;
105 :
106 0 : if (unlikely(src_size % 16 != 0))
107 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
108 :
109 0 : vpaes_cbc_encrypt(src, dst, src_size, ALIGN16(&ctx->expanded_key),
110 0 : ctx->iv, 0);
111 :
112 0 : return 0;
113 : }
114 :
115 0 : static int aes_setiv(void *_ctx, const void *iv, size_t iv_size)
116 : {
117 0 : struct aes_ctx *ctx = _ctx;
118 :
119 0 : if (iv_size != 16)
120 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
121 :
122 0 : memcpy(ctx->iv, iv, 16);
123 0 : return 0;
124 : }
125 :
126 0 : static void aes_deinit(void *_ctx)
127 : {
128 0 : struct aes_ctx *ctx = _ctx;
129 :
130 0 : zeroize_temp_key(ctx, sizeof(*ctx));
131 0 : gnutls_free(ctx);
132 0 : }
133 :
134 :
135 : const gnutls_crypto_cipher_st _gnutls_aes_ssse3 = {
136 : .init = aes_cipher_init,
137 : .setkey = aes_ssse3_cipher_setkey,
138 : .setiv = aes_setiv,
139 : .encrypt = aes_ssse3_encrypt,
140 : .decrypt = aes_ssse3_decrypt,
141 : .deinit = aes_deinit,
142 : };
143 :
|