1 /*
2  * Copyright (C) 2000-2012 Free Software Foundation, Inc.
3  *
4  * Author: Nikos Mavrogiannopoulos
5  *
6  * This file is part of GnuTLS.
7  *
8  * The GnuTLS is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program.  If not, see <https://www.gnu.org/licenses/>
20  *
21  */
22 
23 #ifndef GNUTLS_LIB_CIPHER_INT_H
24 #define GNUTLS_LIB_CIPHER_INT_H
25 
26 #include <gnutls/crypto.h>
27 #include "errors.h"
28 #include <crypto-backend.h>
29 
30 extern int crypto_cipher_prio;
31 extern gnutls_crypto_cipher_st _gnutls_cipher_ops;
32 
33 typedef int (*cipher_encrypt_func) (void *hd, const void *plaintext,
34 				    size_t, void *ciphertext, size_t);
35 typedef int (*cipher_decrypt_func) (void *hd, const void *ciphertext,
36 				    size_t, void *plaintext, size_t);
37 typedef int (*aead_cipher_encrypt_func) (void *hd,
38 					 const void *nonce, size_t,
39 					 const void *auth, size_t,
40 					 size_t tag,
41 					 const void *plaintext, size_t,
42 					 void *ciphertext, size_t);
43 typedef int (*aead_cipher_decrypt_func) (void *hd,
44 					 const void *nonce, size_t,
45 					 const void *auth, size_t,
46 					 size_t tag,
47 					 const void *ciphertext, size_t,
48 					 void *plaintext, size_t);
49 typedef void (*cipher_deinit_func) (void *hd);
50 
51 typedef int (*cipher_auth_func) (void *hd, const void *data, size_t);
52 typedef int (*cipher_setiv_func) (void *hd, const void *iv, size_t);
53 typedef int (*cipher_getiv_func) (void *hd, void *iv, size_t);
54 
55 typedef void (*cipher_tag_func) (void *hd, void *tag, size_t);
56 
57 typedef struct {
58 	void *handle;
59 	const cipher_entry_st *e;
60 	cipher_encrypt_func encrypt;
61 	cipher_decrypt_func decrypt;
62 	aead_cipher_encrypt_func aead_encrypt;
63 	aead_cipher_decrypt_func aead_decrypt;
64 	cipher_auth_func auth;
65 	cipher_tag_func tag;
66 	cipher_setiv_func setiv;
67 	cipher_getiv_func getiv;
68 	cipher_deinit_func deinit;
69 } cipher_hd_st;
70 
71 int _gnutls_cipher_init(cipher_hd_st *, const cipher_entry_st * e,
72 			const gnutls_datum_t * key,
73 			const gnutls_datum_t * iv, int enc);
74 
_gnutls_cipher_setiv(const cipher_hd_st * handle,const void * iv,size_t ivlen)75 inline static int _gnutls_cipher_setiv(const cipher_hd_st * handle,
76 					const void *iv, size_t ivlen)
77 {
78 	return handle->setiv(handle->handle, iv, ivlen);
79 }
80 
_gnutls_cipher_getiv(const cipher_hd_st * handle,void * iv,size_t ivlen)81 inline static int _gnutls_cipher_getiv(const cipher_hd_st * handle,
82 				       void *iv, size_t ivlen)
83 {
84 	if (unlikely(handle == NULL || handle->handle == NULL ||
85 		    handle->getiv == NULL))
86 		return GNUTLS_E_INVALID_REQUEST;
87 
88 	return handle->getiv(handle->handle, iv, ivlen);
89 }
90 
91 inline static int
_gnutls_cipher_encrypt2(const cipher_hd_st * handle,const void * text,size_t textlen,void * ciphertext,size_t ciphertextlen)92 _gnutls_cipher_encrypt2(const cipher_hd_st * handle, const void *text,
93 			size_t textlen, void *ciphertext,
94 			size_t ciphertextlen)
95 {
96 	if (likely(handle != NULL && handle->handle != NULL)) {
97 		if (handle->encrypt == NULL) {
98 			return (GNUTLS_E_INVALID_REQUEST);
99 		}
100 		return handle->encrypt(handle->handle, text, textlen,
101 				       ciphertext, ciphertextlen);
102 	}
103 
104 	return 0;
105 }
106 
107 inline static int
_gnutls_cipher_decrypt2(const cipher_hd_st * handle,const void * ciphertext,size_t ciphertextlen,void * text,size_t textlen)108 _gnutls_cipher_decrypt2(const cipher_hd_st * handle,
109 			const void *ciphertext, size_t ciphertextlen,
110 			void *text, size_t textlen)
111 {
112 	if (likely(handle != NULL && handle->handle != NULL)) {
113 		if (handle->decrypt == NULL) {
114 			return (GNUTLS_E_INVALID_REQUEST);
115 		}
116 		return handle->decrypt(handle->handle, ciphertext,
117 				       ciphertextlen, text, textlen);
118 	}
119 
120 	return 0;
121 }
122 
123 inline static int
_gnutls_aead_cipher_encrypt(const cipher_hd_st * handle,const void * nonce,size_t nonce_len,const void * auth,size_t auth_len,size_t tag,const void * text,size_t textlen,void * ciphertext,size_t ciphertextlen)124 _gnutls_aead_cipher_encrypt(const cipher_hd_st * handle,
125 			    const void *nonce, size_t nonce_len,
126 			    const void *auth, size_t auth_len,
127 			    size_t tag,
128 			    const void *text, size_t textlen,
129 			    void *ciphertext, size_t ciphertextlen)
130 {
131 	if (likely(handle != NULL && handle->handle != NULL && handle->aead_encrypt != NULL)) {
132 		return handle->aead_encrypt(handle->handle,
133 					    nonce, nonce_len,
134 					    auth, auth_len,
135 					    tag,
136 					    text, textlen,
137 					    ciphertext, ciphertextlen);
138 	}
139 
140 	return GNUTLS_E_INVALID_REQUEST;
141 }
142 
143 inline static int
_gnutls_aead_cipher_decrypt(const cipher_hd_st * handle,const void * nonce,size_t nonce_len,const void * auth,size_t auth_len,size_t tag,const void * ciphertext,size_t ciphertextlen,void * text,size_t textlen)144 _gnutls_aead_cipher_decrypt(const cipher_hd_st * handle,
145 			    const void *nonce, size_t nonce_len,
146 			    const void *auth, size_t auth_len,
147 			    size_t tag,
148 			    const void *ciphertext, size_t ciphertextlen,
149 			    void *text, size_t textlen)
150 {
151 	if (likely(handle != NULL && handle->handle != NULL && handle->aead_decrypt != NULL)) {
152 		return handle->aead_decrypt(handle->handle,
153 					    nonce, nonce_len,
154 					    auth, auth_len,
155 					    tag,
156 					    ciphertext, ciphertextlen,
157 					    text, textlen);
158 	}
159 
160 	return GNUTLS_E_INVALID_REQUEST;
161 }
162 
_gnutls_cipher_deinit(cipher_hd_st * handle)163 inline static void _gnutls_cipher_deinit(cipher_hd_st * handle)
164 {
165 	if (likely(handle != NULL && handle->handle != NULL)) {
166 		handle->deinit(handle->handle);
167 		handle->handle = NULL;
168 	}
169 }
170 
171 int _gnutls_cipher_exists(gnutls_cipher_algorithm_t cipher);
172 
173 int _gnutls_cipher_get_iv(gnutls_cipher_hd_t handle, void *iv,
174 			  size_t ivlen);
175 
176 #define _gnutls_cipher_is_aead(h) _gnutls_cipher_algo_is_aead((h)->e)
177 
178 /* returns the tag in AUTHENC ciphers */
_gnutls_cipher_tag(const cipher_hd_st * handle,void * tag,size_t tag_size)179 inline static void _gnutls_cipher_tag(const cipher_hd_st * handle,
180 				      void *tag, size_t tag_size)
181 {
182 	if (likely(handle != NULL && handle->handle != NULL)) {
183 		handle->tag(handle->handle, tag, tag_size);
184 	}
185 }
186 
187 /* Add auth data for AUTHENC ciphers
188  */
_gnutls_cipher_auth(const cipher_hd_st * handle,const void * text,size_t textlen)189 inline static int _gnutls_cipher_auth(const cipher_hd_st * handle,
190 				      const void *text, size_t textlen)
191 {
192 	if (likely(handle != NULL && handle->handle != NULL)) {
193 		return handle->auth(handle->handle, text, textlen);
194 	}
195 	return GNUTLS_E_INTERNAL_ERROR;
196 }
197 
198 #define _gnutls_cipher_encrypt(x,y,z) _gnutls_cipher_encrypt2(x,y,z,y,z)
199 #define _gnutls_cipher_decrypt(x,y,z) _gnutls_cipher_decrypt2(x,y,z,y,z)
200 
201 /* auth_cipher API. Allows combining a cipher with a MAC.
202  */
203 
204 typedef struct {
205 	cipher_hd_st cipher;
206 	union {
207 		digest_hd_st dig;
208 		mac_hd_st mac;
209 	} mac;
210 	unsigned int is_mac:1;
211 #ifdef ENABLE_SSL3
212 	unsigned int ssl_hmac:1;
213 #endif
214 #ifdef ENABLE_GOST
215 	unsigned int continuous_mac:1;
216 #endif
217 	unsigned int non_null:1;
218 	unsigned int etm:1;
219 	size_t tag_size;
220 } auth_cipher_hd_st;
221 
222 int _gnutls_auth_cipher_init(auth_cipher_hd_st * handle,
223 			     const cipher_entry_st * e,
224 			     const gnutls_datum_t * cipher_key,
225 			     const gnutls_datum_t * iv,
226 			     const mac_entry_st * me,
227 			     const gnutls_datum_t * mac_key,
228 			     unsigned etm,
229 #ifdef ENABLE_SSL3
230 			     unsigned ssl_hmac,
231 #endif
232 			     int enc);
233 
234 int _gnutls_auth_cipher_add_auth(auth_cipher_hd_st * handle,
235 				 const void *text, int textlen);
236 
237 int _gnutls_auth_cipher_encrypt2_tag(auth_cipher_hd_st * handle,
238 				     const uint8_t * text, int textlen,
239 				     void *ciphertext, int ciphertextlen,
240 				     int pad_size);
241 int _gnutls_auth_cipher_decrypt2(auth_cipher_hd_st * handle,
242 				 const void *ciphertext, int ciphertextlen,
243 				 void *text, int textlen);
244 int _gnutls_auth_cipher_tag(auth_cipher_hd_st * handle, void *tag,
245 			    int tag_size);
246 
_gnutls_auth_cipher_setiv(const auth_cipher_hd_st * handle,const void * iv,size_t ivlen)247 inline static int _gnutls_auth_cipher_setiv(const auth_cipher_hd_st *
248 					     handle, const void *iv,
249 					     size_t ivlen)
250 {
251 	return _gnutls_cipher_setiv(&handle->cipher, iv, ivlen);
252 }
253 
_gnutls_auth_cipher_tag_len(auth_cipher_hd_st * handle)254 inline static size_t _gnutls_auth_cipher_tag_len(auth_cipher_hd_st *
255 						 handle)
256 {
257 	return handle->tag_size;
258 }
259 
260 #define _gnutls_auth_cipher_is_aead(h) _gnutls_cipher_is_aead(&(h)->cipher)
261 
262 void _gnutls_auth_cipher_deinit(auth_cipher_hd_st * handle);
263 
264 
265 #endif /* GNUTLS_LIB_CIPHER_INT_H */
266