xref: /dragonfly/contrib/wpa_supplicant/src/crypto/crypto_gnutls.c (revision 3a84a4273475ed07d0ab1c2dfeffdfedef35d9cd)
1 /*
2  * WPA Supplicant / wrapper functions for libgcrypt
3  * Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "includes.h"
10 #include <gcrypt.h>
11 
12 #include "common.h"
13 #include "md5.h"
14 #include "sha1.h"
15 #include "sha256.h"
16 #include "sha384.h"
17 #include "sha512.h"
18 #include "crypto.h"
19 
gnutls_digest_vector(int algo,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)20 static int gnutls_digest_vector(int algo, size_t num_elem,
21                                         const u8 *addr[], const size_t *len, u8 *mac)
22 {
23           gcry_md_hd_t hd;
24           unsigned char *p;
25           size_t i;
26 
27           if (TEST_FAIL())
28                     return -1;
29 
30           if (gcry_md_open(&hd, algo, 0) != GPG_ERR_NO_ERROR)
31                     return -1;
32           for (i = 0; i < num_elem; i++)
33                     gcry_md_write(hd, addr[i], len[i]);
34           p = gcry_md_read(hd, algo);
35           if (p)
36                     memcpy(mac, p, gcry_md_get_algo_dlen(algo));
37           gcry_md_close(hd);
38           return 0;
39 }
40 
41 
md4_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)42 int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
43 {
44           return gnutls_digest_vector(GCRY_MD_MD4, num_elem, addr, len, mac);
45 }
46 
47 
des_encrypt(const u8 * clear,const u8 * key,u8 * cypher)48 int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
49 {
50           gcry_cipher_hd_t hd;
51           u8 pkey[8], next, tmp;
52           int i;
53 
54           /* Add parity bits to the key */
55           next = 0;
56           for (i = 0; i < 7; i++) {
57                     tmp = key[i];
58                     pkey[i] = (tmp >> i) | next | 1;
59                     next = tmp << (7 - i);
60           }
61           pkey[i] = next | 1;
62 
63           gcry_cipher_open(&hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
64           gcry_err_code(gcry_cipher_setkey(hd, pkey, 8));
65           gcry_cipher_encrypt(hd, cypher, 8, clear, 8);
66           gcry_cipher_close(hd);
67           return 0;
68 }
69 
70 
md5_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)71 int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
72 {
73           return gnutls_digest_vector(GCRY_MD_MD5, num_elem, addr, len, mac);
74 }
75 
76 
sha1_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)77 int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
78 {
79           return gnutls_digest_vector(GCRY_MD_SHA1, num_elem, addr, len, mac);
80 }
81 
82 
sha256_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)83 int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
84 {
85           return gnutls_digest_vector(GCRY_MD_SHA256, num_elem, addr, len, mac);
86 }
87 
88 
sha384_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)89 int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
90 {
91           return gnutls_digest_vector(GCRY_MD_SHA384, num_elem, addr, len, mac);
92 }
93 
94 
sha512_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)95 int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
96 {
97           return gnutls_digest_vector(GCRY_MD_SHA512, num_elem, addr, len, mac);
98 }
99 
100 
gnutls_hmac_vector(int algo,const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)101 static int gnutls_hmac_vector(int algo, const u8 *key, size_t key_len,
102                                     size_t num_elem, const u8 *addr[],
103                                     const size_t *len, u8 *mac)
104 {
105           gcry_md_hd_t hd;
106           unsigned char *p;
107           size_t i;
108 
109           if (TEST_FAIL())
110                     return -1;
111 
112           if (gcry_md_open(&hd, algo, GCRY_MD_FLAG_HMAC) != GPG_ERR_NO_ERROR)
113                     return -1;
114           if (gcry_md_setkey(hd, key, key_len) != GPG_ERR_NO_ERROR) {
115                     gcry_md_close(hd);
116                     return -1;
117           }
118           for (i = 0; i < num_elem; i++)
119                     gcry_md_write(hd, addr[i], len[i]);
120           p = gcry_md_read(hd, algo);
121           if (p)
122                     memcpy(mac, p, gcry_md_get_algo_dlen(algo));
123           gcry_md_close(hd);
124           return 0;
125 }
126 
127 
hmac_md5_vector(const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)128 int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
129                         const u8 *addr[], const size_t *len, u8 *mac)
130 {
131           return gnutls_hmac_vector(GCRY_MD_MD5, key, key_len, num_elem, addr,
132                                           len, mac);
133 }
134 
135 
hmac_md5(const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * mac)136 int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
137                u8 *mac)
138 {
139           return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac);
140 }
141 
142 
hmac_sha1_vector(const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)143 int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
144                          const u8 *addr[], const size_t *len, u8 *mac)
145 {
146           return gnutls_hmac_vector(GCRY_MD_SHA1, key, key_len, num_elem, addr,
147                                           len, mac);
148 }
149 
150 
hmac_sha1(const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * mac)151 int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
152                  u8 *mac)
153 {
154           return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac);
155 }
156 
157 
158 #ifdef CONFIG_SHA256
159 
hmac_sha256_vector(const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)160 int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
161                            const u8 *addr[], const size_t *len, u8 *mac)
162 {
163           return gnutls_hmac_vector(GCRY_MD_SHA256, key, key_len, num_elem, addr,
164                                           len, mac);
165 }
166 
167 
hmac_sha256(const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * mac)168 int hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
169                     size_t data_len, u8 *mac)
170 {
171           return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
172 }
173 
174 #endif /* CONFIG_SHA256 */
175 
176 
177 #ifdef CONFIG_SHA384
178 
hmac_sha384_vector(const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)179 int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem,
180                            const u8 *addr[], const size_t *len, u8 *mac)
181 {
182           return gnutls_hmac_vector(GCRY_MD_SHA384, key, key_len, num_elem, addr,
183                                           len, mac);
184 }
185 
186 
hmac_sha384(const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * mac)187 int hmac_sha384(const u8 *key, size_t key_len, const u8 *data,
188                     size_t data_len, u8 *mac)
189 {
190           return hmac_sha384_vector(key, key_len, 1, &data, &data_len, mac);
191 }
192 
193 #endif /* CONFIG_SHA384 */
194 
195 
196 #ifdef CONFIG_SHA512
197 
hmac_sha512_vector(const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)198 int hmac_sha512_vector(const u8 *key, size_t key_len, size_t num_elem,
199                            const u8 *addr[], const size_t *len, u8 *mac)
200 {
201           return gnutls_hmac_vector(GCRY_MD_SHA512, key, key_len, num_elem, addr,
202                                           len, mac);
203 }
204 
205 
hmac_sha512(const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * mac)206 int hmac_sha512(const u8 *key, size_t key_len, const u8 *data,
207                     size_t data_len, u8 *mac)
208 {
209           return hmac_sha512_vector(key, key_len, 1, &data, &data_len, mac);
210 }
211 
212 #endif /* CONFIG_SHA512 */
213 
214 
aes_encrypt_init(const u8 * key,size_t len)215 void * aes_encrypt_init(const u8 *key, size_t len)
216 {
217           gcry_cipher_hd_t hd;
218 
219           if (TEST_FAIL())
220                     return NULL;
221 
222           if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) !=
223               GPG_ERR_NO_ERROR) {
224                     printf("cipher open failed\n");
225                     return NULL;
226           }
227           if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) {
228                     printf("setkey failed\n");
229                     gcry_cipher_close(hd);
230                     return NULL;
231           }
232 
233           return hd;
234 }
235 
236 
aes_encrypt(void * ctx,const u8 * plain,u8 * crypt)237 int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
238 {
239           gcry_cipher_hd_t hd = ctx;
240           gcry_cipher_encrypt(hd, crypt, 16, plain, 16);
241           return 0;
242 }
243 
244 
aes_encrypt_deinit(void * ctx)245 void aes_encrypt_deinit(void *ctx)
246 {
247           gcry_cipher_hd_t hd = ctx;
248           gcry_cipher_close(hd);
249 }
250 
251 
aes_decrypt_init(const u8 * key,size_t len)252 void * aes_decrypt_init(const u8 *key, size_t len)
253 {
254           gcry_cipher_hd_t hd;
255 
256           if (TEST_FAIL())
257                     return NULL;
258 
259           if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) !=
260               GPG_ERR_NO_ERROR)
261                     return NULL;
262           if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) {
263                     gcry_cipher_close(hd);
264                     return NULL;
265           }
266 
267           return hd;
268 }
269 
270 
aes_decrypt(void * ctx,const u8 * crypt,u8 * plain)271 int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
272 {
273           gcry_cipher_hd_t hd = ctx;
274           gcry_cipher_decrypt(hd, plain, 16, crypt, 16);
275           return 0;
276 }
277 
278 
aes_decrypt_deinit(void * ctx)279 void aes_decrypt_deinit(void *ctx)
280 {
281           gcry_cipher_hd_t hd = ctx;
282           gcry_cipher_close(hd);
283 }
284 
285 
crypto_dh_init(u8 generator,const u8 * prime,size_t prime_len,u8 * privkey,u8 * pubkey)286 int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey,
287                        u8 *pubkey)
288 {
289           size_t pubkey_len, pad;
290 
291           if (os_get_random(privkey, prime_len) < 0)
292                     return -1;
293           if (os_memcmp(privkey, prime, prime_len) > 0) {
294                     /* Make sure private value is smaller than prime */
295                     privkey[0] = 0;
296           }
297 
298           pubkey_len = prime_len;
299           if (crypto_mod_exp(&generator, 1, privkey, prime_len, prime, prime_len,
300                                  pubkey, &pubkey_len) < 0)
301                     return -1;
302           if (pubkey_len < prime_len) {
303                     pad = prime_len - pubkey_len;
304                     os_memmove(pubkey + pad, pubkey, pubkey_len);
305                     os_memset(pubkey, 0, pad);
306           }
307 
308           return 0;
309 }
310 
311 
crypto_dh_derive_secret(u8 generator,const u8 * prime,size_t prime_len,const u8 * order,size_t order_len,const u8 * privkey,size_t privkey_len,const u8 * pubkey,size_t pubkey_len,u8 * secret,size_t * len)312 int crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len,
313                                   const u8 *order, size_t order_len,
314                                   const u8 *privkey, size_t privkey_len,
315                                   const u8 *pubkey, size_t pubkey_len,
316                                   u8 *secret, size_t *len)
317 {
318           gcry_mpi_t pub = NULL;
319           int res = -1;
320 
321           if (pubkey_len > prime_len ||
322               (pubkey_len == prime_len &&
323                os_memcmp(pubkey, prime, prime_len) >= 0))
324                     return -1;
325 
326           if (gcry_mpi_scan(&pub, GCRYMPI_FMT_USG, pubkey, pubkey_len, NULL) !=
327               GPG_ERR_NO_ERROR ||
328               gcry_mpi_cmp_ui(pub, 1) <= 0)
329                     goto fail;
330 
331           if (order) {
332                     gcry_mpi_t p = NULL, q = NULL, tmp;
333                     int failed;
334 
335                     /* verify: pubkey^q == 1 mod p */
336                     tmp = gcry_mpi_new(prime_len * 8);
337                     failed = !tmp ||
338                               gcry_mpi_scan(&p, GCRYMPI_FMT_USG, prime, prime_len,
339                                               NULL) != GPG_ERR_NO_ERROR ||
340                               gcry_mpi_scan(&q, GCRYMPI_FMT_USG, order, order_len,
341                                               NULL) != GPG_ERR_NO_ERROR;
342                     if (!failed) {
343                               gcry_mpi_powm(tmp, pub, q, p);
344                               failed = gcry_mpi_cmp_ui(tmp, 1) != 0;
345                     }
346                     gcry_mpi_release(p);
347                     gcry_mpi_release(q);
348                     gcry_mpi_release(tmp);
349                     if (failed)
350                               goto fail;
351           }
352 
353           res = crypto_mod_exp(pubkey, pubkey_len, privkey, privkey_len,
354                                    prime, prime_len, secret, len);
355 fail:
356           gcry_mpi_release(pub);
357           return res;
358 }
359 
360 
crypto_mod_exp(const u8 * base,size_t base_len,const u8 * power,size_t power_len,const u8 * modulus,size_t modulus_len,u8 * result,size_t * result_len)361 int crypto_mod_exp(const u8 *base, size_t base_len,
362                        const u8 *power, size_t power_len,
363                        const u8 *modulus, size_t modulus_len,
364                        u8 *result, size_t *result_len)
365 {
366           gcry_mpi_t bn_base = NULL, bn_exp = NULL, bn_modulus = NULL,
367                     bn_result = NULL;
368           int ret = -1;
369 
370           if (gcry_mpi_scan(&bn_base, GCRYMPI_FMT_USG, base, base_len, NULL) !=
371               GPG_ERR_NO_ERROR ||
372               gcry_mpi_scan(&bn_exp, GCRYMPI_FMT_USG, power, power_len, NULL) !=
373               GPG_ERR_NO_ERROR ||
374               gcry_mpi_scan(&bn_modulus, GCRYMPI_FMT_USG, modulus, modulus_len,
375                                 NULL) != GPG_ERR_NO_ERROR)
376                     goto error;
377           bn_result = gcry_mpi_new(modulus_len * 8);
378 
379           gcry_mpi_powm(bn_result, bn_base, bn_exp, bn_modulus);
380 
381           if (gcry_mpi_print(GCRYMPI_FMT_USG, result, *result_len, result_len,
382                                  bn_result) != GPG_ERR_NO_ERROR)
383                     goto error;
384 
385           ret = 0;
386 
387 error:
388           gcry_mpi_release(bn_base);
389           gcry_mpi_release(bn_exp);
390           gcry_mpi_release(bn_modulus);
391           gcry_mpi_release(bn_result);
392           return ret;
393 }
394 
395 
396 struct crypto_cipher {
397           gcry_cipher_hd_t enc;
398           gcry_cipher_hd_t dec;
399 };
400 
401 
crypto_cipher_init(enum crypto_cipher_alg alg,const u8 * iv,const u8 * key,size_t key_len)402 struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
403                                                     const u8 *iv, const u8 *key,
404                                                     size_t key_len)
405 {
406           struct crypto_cipher *ctx;
407           gcry_error_t res;
408           enum gcry_cipher_algos a;
409           int ivlen;
410 
411           ctx = os_zalloc(sizeof(*ctx));
412           if (ctx == NULL)
413                     return NULL;
414 
415           switch (alg) {
416           case CRYPTO_CIPHER_ALG_RC4:
417                     a = GCRY_CIPHER_ARCFOUR;
418                     res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_STREAM,
419                                                0);
420                     gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_STREAM, 0);
421                     break;
422           case CRYPTO_CIPHER_ALG_AES:
423                     if (key_len == 24)
424                               a = GCRY_CIPHER_AES192;
425                     else if (key_len == 32)
426                               a = GCRY_CIPHER_AES256;
427                     else
428                               a = GCRY_CIPHER_AES;
429                     res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
430                     gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
431                     break;
432           case CRYPTO_CIPHER_ALG_3DES:
433                     a = GCRY_CIPHER_3DES;
434                     res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
435                     gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
436                     break;
437           case CRYPTO_CIPHER_ALG_DES:
438                     a = GCRY_CIPHER_DES;
439                     res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
440                     gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
441                     break;
442           case CRYPTO_CIPHER_ALG_RC2:
443                     if (key_len == 5)
444                               a = GCRY_CIPHER_RFC2268_40;
445                     else
446                               a = GCRY_CIPHER_RFC2268_128;
447                     res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0);
448                     gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0);
449                     break;
450           default:
451                     os_free(ctx);
452                     return NULL;
453           }
454 
455           if (res != GPG_ERR_NO_ERROR) {
456                     os_free(ctx);
457                     return NULL;
458           }
459 
460           if (gcry_cipher_setkey(ctx->enc, key, key_len) != GPG_ERR_NO_ERROR ||
461               gcry_cipher_setkey(ctx->dec, key, key_len) != GPG_ERR_NO_ERROR) {
462                     gcry_cipher_close(ctx->enc);
463                     gcry_cipher_close(ctx->dec);
464                     os_free(ctx);
465                     return NULL;
466           }
467 
468           ivlen = gcry_cipher_get_algo_blklen(a);
469           if (gcry_cipher_setiv(ctx->enc, iv, ivlen) != GPG_ERR_NO_ERROR ||
470               gcry_cipher_setiv(ctx->dec, iv, ivlen) != GPG_ERR_NO_ERROR) {
471                     gcry_cipher_close(ctx->enc);
472                     gcry_cipher_close(ctx->dec);
473                     os_free(ctx);
474                     return NULL;
475           }
476 
477           return ctx;
478 }
479 
480 
crypto_cipher_encrypt(struct crypto_cipher * ctx,const u8 * plain,u8 * crypt,size_t len)481 int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
482                                 u8 *crypt, size_t len)
483 {
484           if (gcry_cipher_encrypt(ctx->enc, crypt, len, plain, len) !=
485               GPG_ERR_NO_ERROR)
486                     return -1;
487           return 0;
488 }
489 
490 
crypto_cipher_decrypt(struct crypto_cipher * ctx,const u8 * crypt,u8 * plain,size_t len)491 int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
492                                 u8 *plain, size_t len)
493 {
494           if (gcry_cipher_decrypt(ctx->dec, plain, len, crypt, len) !=
495               GPG_ERR_NO_ERROR)
496                     return -1;
497           return 0;
498 }
499 
500 
crypto_cipher_deinit(struct crypto_cipher * ctx)501 void crypto_cipher_deinit(struct crypto_cipher *ctx)
502 {
503           gcry_cipher_close(ctx->enc);
504           gcry_cipher_close(ctx->dec);
505           os_free(ctx);
506 }
507