Add qemu 2.4.0
[kvmfornfv.git] / qemu / crypto / cipher-nettle.c
1 /*
2  * QEMU Crypto cipher nettle algorithms
3  *
4  * Copyright (c) 2015 Red Hat, Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include <nettle/nettle-types.h>
22 #include <nettle/aes.h>
23 #include <nettle/des.h>
24 #include <nettle/cbc.h>
25
26 #if CONFIG_NETTLE_VERSION_MAJOR < 3
27 typedef nettle_crypt_func nettle_cipher_func;
28
29 typedef void *       cipher_ctx_t;
30 typedef unsigned     cipher_length_t;
31 #else
32 typedef const void * cipher_ctx_t;
33 typedef size_t       cipher_length_t;
34 #endif
35
36 static nettle_cipher_func aes_encrypt_wrapper;
37 static nettle_cipher_func aes_decrypt_wrapper;
38 static nettle_cipher_func des_encrypt_wrapper;
39 static nettle_cipher_func des_decrypt_wrapper;
40
41 static void aes_encrypt_wrapper(cipher_ctx_t ctx, cipher_length_t length,
42                                 uint8_t *dst, const uint8_t *src)
43 {
44     aes_encrypt(ctx, length, dst, src);
45 }
46
47 static void aes_decrypt_wrapper(cipher_ctx_t ctx, cipher_length_t length,
48                                 uint8_t *dst, const uint8_t *src)
49 {
50     aes_decrypt(ctx, length, dst, src);
51 }
52
53 static void des_encrypt_wrapper(cipher_ctx_t ctx, cipher_length_t length,
54                                 uint8_t *dst, const uint8_t *src)
55 {
56     des_encrypt(ctx, length, dst, src);
57 }
58
59 static void des_decrypt_wrapper(cipher_ctx_t ctx, cipher_length_t length,
60                                 uint8_t *dst, const uint8_t *src)
61 {
62     des_decrypt(ctx, length, dst, src);
63 }
64
65 typedef struct QCryptoCipherNettle QCryptoCipherNettle;
66 struct QCryptoCipherNettle {
67     void *ctx_encrypt;
68     void *ctx_decrypt;
69     nettle_cipher_func *alg_encrypt;
70     nettle_cipher_func *alg_decrypt;
71     uint8_t *iv;
72     size_t niv;
73 };
74
75 bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg)
76 {
77     switch (alg) {
78     case QCRYPTO_CIPHER_ALG_DES_RFB:
79     case QCRYPTO_CIPHER_ALG_AES_128:
80     case QCRYPTO_CIPHER_ALG_AES_192:
81     case QCRYPTO_CIPHER_ALG_AES_256:
82         return true;
83     default:
84         return false;
85     }
86 }
87
88
89 QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
90                                   QCryptoCipherMode mode,
91                                   const uint8_t *key, size_t nkey,
92                                   Error **errp)
93 {
94     QCryptoCipher *cipher;
95     QCryptoCipherNettle *ctx;
96     uint8_t *rfbkey;
97
98     switch (mode) {
99     case QCRYPTO_CIPHER_MODE_ECB:
100     case QCRYPTO_CIPHER_MODE_CBC:
101         break;
102     default:
103         error_setg(errp, "Unsupported cipher mode %d", mode);
104         return NULL;
105     }
106
107     if (!qcrypto_cipher_validate_key_length(alg, nkey, errp)) {
108         return NULL;
109     }
110
111     cipher = g_new0(QCryptoCipher, 1);
112     cipher->alg = alg;
113     cipher->mode = mode;
114
115     ctx = g_new0(QCryptoCipherNettle, 1);
116
117     switch (alg) {
118     case QCRYPTO_CIPHER_ALG_DES_RFB:
119         ctx->ctx_encrypt = g_new0(struct des_ctx, 1);
120         ctx->ctx_decrypt = NULL; /* 1 ctx can do both */
121         rfbkey = qcrypto_cipher_munge_des_rfb_key(key, nkey);
122         des_set_key(ctx->ctx_encrypt, rfbkey);
123         g_free(rfbkey);
124
125         ctx->alg_encrypt = des_encrypt_wrapper;
126         ctx->alg_decrypt = des_decrypt_wrapper;
127
128         ctx->niv = DES_BLOCK_SIZE;
129         break;
130
131     case QCRYPTO_CIPHER_ALG_AES_128:
132     case QCRYPTO_CIPHER_ALG_AES_192:
133     case QCRYPTO_CIPHER_ALG_AES_256:
134         ctx->ctx_encrypt = g_new0(struct aes_ctx, 1);
135         ctx->ctx_decrypt = g_new0(struct aes_ctx, 1);
136
137         aes_set_encrypt_key(ctx->ctx_encrypt, nkey, key);
138         aes_set_decrypt_key(ctx->ctx_decrypt, nkey, key);
139
140         ctx->alg_encrypt = aes_encrypt_wrapper;
141         ctx->alg_decrypt = aes_decrypt_wrapper;
142
143         ctx->niv = AES_BLOCK_SIZE;
144         break;
145     default:
146         error_setg(errp, "Unsupported cipher algorithm %d", alg);
147         goto error;
148     }
149
150     ctx->iv = g_new0(uint8_t, ctx->niv);
151     cipher->opaque = ctx;
152
153     return cipher;
154
155  error:
156     g_free(cipher);
157     g_free(ctx);
158     return NULL;
159 }
160
161
162 void qcrypto_cipher_free(QCryptoCipher *cipher)
163 {
164     QCryptoCipherNettle *ctx;
165
166     if (!cipher) {
167         return;
168     }
169
170     ctx = cipher->opaque;
171     g_free(ctx->iv);
172     g_free(ctx->ctx_encrypt);
173     g_free(ctx->ctx_decrypt);
174     g_free(ctx);
175     g_free(cipher);
176 }
177
178
179 int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
180                            const void *in,
181                            void *out,
182                            size_t len,
183                            Error **errp)
184 {
185     QCryptoCipherNettle *ctx = cipher->opaque;
186
187     switch (cipher->mode) {
188     case QCRYPTO_CIPHER_MODE_ECB:
189         ctx->alg_encrypt(ctx->ctx_encrypt, len, out, in);
190         break;
191
192     case QCRYPTO_CIPHER_MODE_CBC:
193         cbc_encrypt(ctx->ctx_encrypt, ctx->alg_encrypt,
194                     ctx->niv, ctx->iv,
195                     len, out, in);
196         break;
197     default:
198         error_setg(errp, "Unsupported cipher algorithm %d",
199                    cipher->alg);
200         return -1;
201     }
202     return 0;
203 }
204
205
206 int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
207                            const void *in,
208                            void *out,
209                            size_t len,
210                            Error **errp)
211 {
212     QCryptoCipherNettle *ctx = cipher->opaque;
213
214     switch (cipher->mode) {
215     case QCRYPTO_CIPHER_MODE_ECB:
216         ctx->alg_decrypt(ctx->ctx_decrypt ? ctx->ctx_decrypt : ctx->ctx_encrypt,
217                          len, out, in);
218         break;
219
220     case QCRYPTO_CIPHER_MODE_CBC:
221         cbc_decrypt(ctx->ctx_decrypt ? ctx->ctx_decrypt : ctx->ctx_encrypt,
222                     ctx->alg_decrypt, ctx->niv, ctx->iv,
223                     len, out, in);
224         break;
225     default:
226         error_setg(errp, "Unsupported cipher algorithm %d",
227                    cipher->alg);
228         return -1;
229     }
230     return 0;
231 }
232
233 int qcrypto_cipher_setiv(QCryptoCipher *cipher,
234                          const uint8_t *iv, size_t niv,
235                          Error **errp)
236 {
237     QCryptoCipherNettle *ctx = cipher->opaque;
238     if (niv != ctx->niv) {
239         error_setg(errp, "Expected IV size %zu not %zu",
240                    ctx->niv, niv);
241         return -1;
242     }
243     memcpy(ctx->iv, iv, niv);
244     return 0;
245 }