$search
00001 /* 00002 * WPA Supplicant / Crypto wrapper for LibTomCrypt (for internal TLSv1) 00003 * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 #include <tomcrypt.h> 00017 00018 #include "common.h" 00019 #include "crypto.h" 00020 00021 #ifndef mp_init_multi 00022 #define mp_init_multi ltc_init_multi 00023 #define mp_clear_multi ltc_deinit_multi 00024 #define mp_unsigned_bin_size(a) ltc_mp.unsigned_size(a) 00025 #define mp_to_unsigned_bin(a, b) ltc_mp.unsigned_write(a, b) 00026 #define mp_read_unsigned_bin(a, b, c) ltc_mp.unsigned_read(a, b, c) 00027 #define mp_exptmod(a,b,c,d) ltc_mp.exptmod(a,b,c,d) 00028 #endif 00029 00030 00031 int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 00032 { 00033 hash_state md; 00034 size_t i; 00035 00036 md4_init(&md); 00037 for (i = 0; i < num_elem; i++) 00038 md4_process(&md, addr[i], len[i]); 00039 md4_done(&md, mac); 00040 return 0; 00041 } 00042 00043 00044 void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) 00045 { 00046 u8 pkey[8], next, tmp; 00047 int i; 00048 symmetric_key skey; 00049 00050 /* Add parity bits to the key */ 00051 next = 0; 00052 for (i = 0; i < 7; i++) { 00053 tmp = key[i]; 00054 pkey[i] = (tmp >> i) | next | 1; 00055 next = tmp << (7 - i); 00056 } 00057 pkey[i] = next | 1; 00058 00059 des_setup(pkey, 8, 0, &skey); 00060 des_ecb_encrypt(clear, cypher, &skey); 00061 des_done(&skey); 00062 } 00063 00064 00065 int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 00066 { 00067 hash_state md; 00068 size_t i; 00069 00070 md5_init(&md); 00071 for (i = 0; i < num_elem; i++) 00072 md5_process(&md, addr[i], len[i]); 00073 md5_done(&md, mac); 00074 return 0; 00075 } 00076 00077 00078 int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 00079 { 00080 hash_state md; 00081 size_t i; 00082 00083 sha1_init(&md); 00084 for (i = 0; i < num_elem; i++) 00085 sha1_process(&md, addr[i], len[i]); 00086 sha1_done(&md, mac); 00087 return 0; 00088 } 00089 00090 00091 void * aes_encrypt_init(const u8 *key, size_t len) 00092 { 00093 symmetric_key *skey; 00094 skey = os_malloc(sizeof(*skey)); 00095 if (skey == NULL) 00096 return NULL; 00097 if (aes_setup(key, len, 0, skey) != CRYPT_OK) { 00098 os_free(skey); 00099 return NULL; 00100 } 00101 return skey; 00102 } 00103 00104 00105 void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) 00106 { 00107 symmetric_key *skey = ctx; 00108 aes_ecb_encrypt(plain, crypt, skey); 00109 } 00110 00111 00112 void aes_encrypt_deinit(void *ctx) 00113 { 00114 symmetric_key *skey = ctx; 00115 aes_done(skey); 00116 os_free(skey); 00117 } 00118 00119 00120 void * aes_decrypt_init(const u8 *key, size_t len) 00121 { 00122 symmetric_key *skey; 00123 skey = os_malloc(sizeof(*skey)); 00124 if (skey == NULL) 00125 return NULL; 00126 if (aes_setup(key, len, 0, skey) != CRYPT_OK) { 00127 os_free(skey); 00128 return NULL; 00129 } 00130 return skey; 00131 } 00132 00133 00134 void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) 00135 { 00136 symmetric_key *skey = ctx; 00137 aes_ecb_encrypt(plain, (u8 *) crypt, skey); 00138 } 00139 00140 00141 void aes_decrypt_deinit(void *ctx) 00142 { 00143 symmetric_key *skey = ctx; 00144 aes_done(skey); 00145 os_free(skey); 00146 } 00147 00148 00149 struct crypto_hash { 00150 enum crypto_hash_alg alg; 00151 int error; 00152 union { 00153 hash_state md; 00154 hmac_state hmac; 00155 } u; 00156 }; 00157 00158 00159 struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, 00160 size_t key_len) 00161 { 00162 struct crypto_hash *ctx; 00163 00164 ctx = os_zalloc(sizeof(*ctx)); 00165 if (ctx == NULL) 00166 return NULL; 00167 00168 ctx->alg = alg; 00169 00170 switch (alg) { 00171 case CRYPTO_HASH_ALG_MD5: 00172 if (md5_init(&ctx->u.md) != CRYPT_OK) 00173 goto fail; 00174 break; 00175 case CRYPTO_HASH_ALG_SHA1: 00176 if (sha1_init(&ctx->u.md) != CRYPT_OK) 00177 goto fail; 00178 break; 00179 case CRYPTO_HASH_ALG_HMAC_MD5: 00180 if (hmac_init(&ctx->u.hmac, find_hash("md5"), key, key_len) != 00181 CRYPT_OK) 00182 goto fail; 00183 break; 00184 case CRYPTO_HASH_ALG_HMAC_SHA1: 00185 if (hmac_init(&ctx->u.hmac, find_hash("sha1"), key, key_len) != 00186 CRYPT_OK) 00187 goto fail; 00188 break; 00189 default: 00190 goto fail; 00191 } 00192 00193 return ctx; 00194 00195 fail: 00196 os_free(ctx); 00197 return NULL; 00198 } 00199 00200 void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) 00201 { 00202 if (ctx == NULL || ctx->error) 00203 return; 00204 00205 switch (ctx->alg) { 00206 case CRYPTO_HASH_ALG_MD5: 00207 ctx->error = md5_process(&ctx->u.md, data, len) != CRYPT_OK; 00208 break; 00209 case CRYPTO_HASH_ALG_SHA1: 00210 ctx->error = sha1_process(&ctx->u.md, data, len) != CRYPT_OK; 00211 break; 00212 case CRYPTO_HASH_ALG_HMAC_MD5: 00213 case CRYPTO_HASH_ALG_HMAC_SHA1: 00214 ctx->error = hmac_process(&ctx->u.hmac, data, len) != CRYPT_OK; 00215 break; 00216 } 00217 } 00218 00219 00220 int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) 00221 { 00222 int ret = 0; 00223 unsigned long clen; 00224 00225 if (ctx == NULL) 00226 return -2; 00227 00228 if (mac == NULL || len == NULL) { 00229 os_free(ctx); 00230 return 0; 00231 } 00232 00233 if (ctx->error) { 00234 os_free(ctx); 00235 return -2; 00236 } 00237 00238 switch (ctx->alg) { 00239 case CRYPTO_HASH_ALG_MD5: 00240 if (*len < 16) { 00241 *len = 16; 00242 os_free(ctx); 00243 return -1; 00244 } 00245 *len = 16; 00246 if (md5_done(&ctx->u.md, mac) != CRYPT_OK) 00247 ret = -2; 00248 break; 00249 case CRYPTO_HASH_ALG_SHA1: 00250 if (*len < 20) { 00251 *len = 20; 00252 os_free(ctx); 00253 return -1; 00254 } 00255 *len = 20; 00256 if (sha1_done(&ctx->u.md, mac) != CRYPT_OK) 00257 ret = -2; 00258 break; 00259 case CRYPTO_HASH_ALG_HMAC_SHA1: 00260 if (*len < 20) { 00261 *len = 20; 00262 os_free(ctx); 00263 return -1; 00264 } 00265 /* continue */ 00266 case CRYPTO_HASH_ALG_HMAC_MD5: 00267 if (*len < 16) { 00268 *len = 16; 00269 os_free(ctx); 00270 return -1; 00271 } 00272 clen = *len; 00273 if (hmac_done(&ctx->u.hmac, mac, &clen) != CRYPT_OK) { 00274 os_free(ctx); 00275 return -1; 00276 } 00277 *len = clen; 00278 break; 00279 default: 00280 ret = -2; 00281 break; 00282 } 00283 00284 os_free(ctx); 00285 00286 return ret; 00287 } 00288 00289 00290 struct crypto_cipher { 00291 int rc4; 00292 union { 00293 symmetric_CBC cbc; 00294 struct { 00295 size_t used_bytes; 00296 u8 key[16]; 00297 size_t keylen; 00298 } rc4; 00299 } u; 00300 }; 00301 00302 00303 struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, 00304 const u8 *iv, const u8 *key, 00305 size_t key_len) 00306 { 00307 struct crypto_cipher *ctx; 00308 int idx, res, rc4 = 0; 00309 00310 switch (alg) { 00311 case CRYPTO_CIPHER_ALG_AES: 00312 idx = find_cipher("aes"); 00313 break; 00314 case CRYPTO_CIPHER_ALG_3DES: 00315 idx = find_cipher("3des"); 00316 break; 00317 case CRYPTO_CIPHER_ALG_DES: 00318 idx = find_cipher("des"); 00319 break; 00320 case CRYPTO_CIPHER_ALG_RC2: 00321 idx = find_cipher("rc2"); 00322 break; 00323 case CRYPTO_CIPHER_ALG_RC4: 00324 idx = -1; 00325 rc4 = 1; 00326 break; 00327 default: 00328 return NULL; 00329 } 00330 00331 ctx = os_zalloc(sizeof(*ctx)); 00332 if (ctx == NULL) 00333 return NULL; 00334 00335 if (rc4) { 00336 ctx->rc4 = 1; 00337 if (key_len > sizeof(ctx->u.rc4.key)) { 00338 os_free(ctx); 00339 return NULL; 00340 } 00341 ctx->u.rc4.keylen = key_len; 00342 os_memcpy(ctx->u.rc4.key, key, key_len); 00343 } else { 00344 res = cbc_start(idx, iv, key, key_len, 0, &ctx->u.cbc); 00345 if (res != CRYPT_OK) { 00346 wpa_printf(MSG_DEBUG, "LibTomCrypt: Cipher start " 00347 "failed: %s", error_to_string(res)); 00348 os_free(ctx); 00349 return NULL; 00350 } 00351 } 00352 00353 return ctx; 00354 } 00355 00356 int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, 00357 u8 *crypt, size_t len) 00358 { 00359 int res; 00360 00361 if (ctx->rc4) { 00362 if (plain != crypt) 00363 os_memcpy(crypt, plain, len); 00364 rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, 00365 ctx->u.rc4.used_bytes, crypt, len); 00366 ctx->u.rc4.used_bytes += len; 00367 return 0; 00368 } 00369 00370 res = cbc_encrypt(plain, crypt, len, &ctx->u.cbc); 00371 if (res != CRYPT_OK) { 00372 wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC encryption " 00373 "failed: %s", error_to_string(res)); 00374 return -1; 00375 } 00376 return 0; 00377 } 00378 00379 00380 int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, 00381 u8 *plain, size_t len) 00382 { 00383 int res; 00384 00385 if (ctx->rc4) { 00386 if (plain != crypt) 00387 os_memcpy(plain, crypt, len); 00388 rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, 00389 ctx->u.rc4.used_bytes, plain, len); 00390 ctx->u.rc4.used_bytes += len; 00391 return 0; 00392 } 00393 00394 res = cbc_decrypt(crypt, plain, len, &ctx->u.cbc); 00395 if (res != CRYPT_OK) { 00396 wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC decryption " 00397 "failed: %s", error_to_string(res)); 00398 return -1; 00399 } 00400 00401 return 0; 00402 } 00403 00404 00405 void crypto_cipher_deinit(struct crypto_cipher *ctx) 00406 { 00407 if (!ctx->rc4) 00408 cbc_done(&ctx->u.cbc); 00409 os_free(ctx); 00410 } 00411 00412 00413 struct crypto_public_key { 00414 rsa_key rsa; 00415 }; 00416 00417 struct crypto_private_key { 00418 rsa_key rsa; 00419 }; 00420 00421 00422 struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len) 00423 { 00424 int res; 00425 struct crypto_public_key *pk; 00426 00427 pk = os_zalloc(sizeof(*pk)); 00428 if (pk == NULL) 00429 return NULL; 00430 00431 res = rsa_import(key, len, &pk->rsa); 00432 if (res != CRYPT_OK) { 00433 wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import " 00434 "public key (res=%d '%s')", 00435 res, error_to_string(res)); 00436 os_free(pk); 00437 return NULL; 00438 } 00439 00440 if (pk->rsa.type != PK_PUBLIC) { 00441 wpa_printf(MSG_ERROR, "LibTomCrypt: Public key was not of " 00442 "correct type"); 00443 rsa_free(&pk->rsa); 00444 os_free(pk); 00445 return NULL; 00446 } 00447 00448 return pk; 00449 } 00450 00451 00452 struct crypto_private_key * crypto_private_key_import(const u8 *key, 00453 size_t len, 00454 const char *passwd) 00455 { 00456 int res; 00457 struct crypto_private_key *pk; 00458 00459 pk = os_zalloc(sizeof(*pk)); 00460 if (pk == NULL) 00461 return NULL; 00462 00463 res = rsa_import(key, len, &pk->rsa); 00464 if (res != CRYPT_OK) { 00465 wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import " 00466 "private key (res=%d '%s')", 00467 res, error_to_string(res)); 00468 os_free(pk); 00469 return NULL; 00470 } 00471 00472 if (pk->rsa.type != PK_PRIVATE) { 00473 wpa_printf(MSG_ERROR, "LibTomCrypt: Private key was not of " 00474 "correct type"); 00475 rsa_free(&pk->rsa); 00476 os_free(pk); 00477 return NULL; 00478 } 00479 00480 return pk; 00481 } 00482 00483 00484 struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf, 00485 size_t len) 00486 { 00487 /* No X.509 support in LibTomCrypt */ 00488 return NULL; 00489 } 00490 00491 00492 static int pkcs1_generate_encryption_block(u8 block_type, size_t modlen, 00493 const u8 *in, size_t inlen, 00494 u8 *out, size_t *outlen) 00495 { 00496 size_t ps_len; 00497 u8 *pos; 00498 00499 /* 00500 * PKCS #1 v1.5, 8.1: 00501 * 00502 * EB = 00 || BT || PS || 00 || D 00503 * BT = 00 or 01 for private-key operation; 02 for public-key operation 00504 * PS = k-3-||D||; at least eight octets 00505 * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero) 00506 * k = length of modulus in octets (modlen) 00507 */ 00508 00509 if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) { 00510 wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer " 00511 "lengths (modlen=%lu outlen=%lu inlen=%lu)", 00512 __func__, (unsigned long) modlen, 00513 (unsigned long) *outlen, 00514 (unsigned long) inlen); 00515 return -1; 00516 } 00517 00518 pos = out; 00519 *pos++ = 0x00; 00520 *pos++ = block_type; /* BT */ 00521 ps_len = modlen - inlen - 3; 00522 switch (block_type) { 00523 case 0: 00524 os_memset(pos, 0x00, ps_len); 00525 pos += ps_len; 00526 break; 00527 case 1: 00528 os_memset(pos, 0xff, ps_len); 00529 pos += ps_len; 00530 break; 00531 case 2: 00532 if (os_get_random(pos, ps_len) < 0) { 00533 wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get " 00534 "random data for PS", __func__); 00535 return -1; 00536 } 00537 while (ps_len--) { 00538 if (*pos == 0x00) 00539 *pos = 0x01; 00540 pos++; 00541 } 00542 break; 00543 default: 00544 wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type " 00545 "%d", __func__, block_type); 00546 return -1; 00547 } 00548 *pos++ = 0x00; 00549 os_memcpy(pos, in, inlen); /* D */ 00550 00551 return 0; 00552 } 00553 00554 00555 static int crypto_rsa_encrypt_pkcs1(int block_type, rsa_key *key, int key_type, 00556 const u8 *in, size_t inlen, 00557 u8 *out, size_t *outlen) 00558 { 00559 unsigned long len, modlen; 00560 int res; 00561 00562 modlen = mp_unsigned_bin_size(key->N); 00563 00564 if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen, 00565 out, outlen) < 0) 00566 return -1; 00567 00568 len = *outlen; 00569 res = rsa_exptmod(out, modlen, out, &len, key_type, key); 00570 if (res != CRYPT_OK) { 00571 wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s", 00572 error_to_string(res)); 00573 return -1; 00574 } 00575 *outlen = len; 00576 00577 return 0; 00578 } 00579 00580 00581 int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key, 00582 const u8 *in, size_t inlen, 00583 u8 *out, size_t *outlen) 00584 { 00585 return crypto_rsa_encrypt_pkcs1(2, &key->rsa, PK_PUBLIC, in, inlen, 00586 out, outlen); 00587 } 00588 00589 00590 int crypto_private_key_sign_pkcs1(struct crypto_private_key *key, 00591 const u8 *in, size_t inlen, 00592 u8 *out, size_t *outlen) 00593 { 00594 return crypto_rsa_encrypt_pkcs1(1, &key->rsa, PK_PRIVATE, in, inlen, 00595 out, outlen); 00596 } 00597 00598 00599 void crypto_public_key_free(struct crypto_public_key *key) 00600 { 00601 if (key) { 00602 rsa_free(&key->rsa); 00603 os_free(key); 00604 } 00605 } 00606 00607 00608 void crypto_private_key_free(struct crypto_private_key *key) 00609 { 00610 if (key) { 00611 rsa_free(&key->rsa); 00612 os_free(key); 00613 } 00614 } 00615 00616 00617 int crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key, 00618 const u8 *crypt, size_t crypt_len, 00619 u8 *plain, size_t *plain_len) 00620 { 00621 int res; 00622 unsigned long len; 00623 u8 *pos; 00624 00625 len = *plain_len; 00626 res = rsa_exptmod(crypt, crypt_len, plain, &len, PK_PUBLIC, 00627 &key->rsa); 00628 if (res != CRYPT_OK) { 00629 wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s", 00630 error_to_string(res)); 00631 return -1; 00632 } 00633 00634 /* 00635 * PKCS #1 v1.5, 8.1: 00636 * 00637 * EB = 00 || BT || PS || 00 || D 00638 * BT = 01 00639 * PS = k-3-||D|| times FF 00640 * k = length of modulus in octets 00641 */ 00642 00643 if (len < 3 + 8 + 16 /* min hash len */ || 00644 plain[0] != 0x00 || plain[1] != 0x01 || plain[2] != 0xff) { 00645 wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " 00646 "structure"); 00647 return -1; 00648 } 00649 00650 pos = plain + 3; 00651 while (pos < plain + len && *pos == 0xff) 00652 pos++; 00653 if (pos - plain - 2 < 8) { 00654 /* PKCS #1 v1.5, 8.1: At least eight octets long PS */ 00655 wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature " 00656 "padding"); 00657 return -1; 00658 } 00659 00660 if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) { 00661 wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " 00662 "structure (2)"); 00663 return -1; 00664 } 00665 pos++; 00666 len -= pos - plain; 00667 00668 /* Strip PKCS #1 header */ 00669 os_memmove(plain, pos, len); 00670 *plain_len = len; 00671 00672 return 0; 00673 } 00674 00675 00676 int crypto_global_init(void) 00677 { 00678 ltc_mp = tfm_desc; 00679 /* TODO: only register algorithms that are really needed */ 00680 if (register_hash(&md4_desc) < 0 || 00681 register_hash(&md5_desc) < 0 || 00682 register_hash(&sha1_desc) < 0 || 00683 register_cipher(&aes_desc) < 0 || 00684 register_cipher(&des_desc) < 0 || 00685 register_cipher(&des3_desc) < 0) { 00686 wpa_printf(MSG_ERROR, "TLSv1: Failed to register " 00687 "hash/cipher functions"); 00688 return -1; 00689 } 00690 00691 return 0; 00692 } 00693 00694 00695 void crypto_global_deinit(void) 00696 { 00697 } 00698 00699 00700 #ifdef CONFIG_MODEXP 00701 00702 int crypto_mod_exp(const u8 *base, size_t base_len, 00703 const u8 *power, size_t power_len, 00704 const u8 *modulus, size_t modulus_len, 00705 u8 *result, size_t *result_len) 00706 { 00707 void *b, *p, *m, *r; 00708 00709 if (mp_init_multi(&b, &p, &m, &r, NULL) != CRYPT_OK) 00710 return -1; 00711 00712 if (mp_read_unsigned_bin(b, (u8 *) base, base_len) != CRYPT_OK || 00713 mp_read_unsigned_bin(p, (u8 *) power, power_len) != CRYPT_OK || 00714 mp_read_unsigned_bin(m, (u8 *) modulus, modulus_len) != CRYPT_OK) 00715 goto fail; 00716 00717 if (mp_exptmod(b, p, m, r) != CRYPT_OK) 00718 goto fail; 00719 00720 *result_len = mp_unsigned_bin_size(r); 00721 if (mp_to_unsigned_bin(r, result) != CRYPT_OK) 00722 goto fail; 00723 00724 mp_clear_multi(b, p, m, r, NULL); 00725 return 0; 00726 00727 fail: 00728 mp_clear_multi(b, p, m, r, NULL); 00729 return -1; 00730 } 00731 00732 #endif /* CONFIG_MODEXP */