123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726 |
- #include "includes.h"
- #include <tomcrypt.h>
- #include "common.h"
- #include "crypto.h"
- #ifndef mp_init_multi
- #define mp_init_multi ltc_init_multi
- #define mp_clear_multi ltc_deinit_multi
- #define mp_unsigned_bin_size(a) ltc_mp.unsigned_size(a)
- #define mp_to_unsigned_bin(a, b) ltc_mp.unsigned_write(a, b)
- #define mp_read_unsigned_bin(a, b, c) ltc_mp.unsigned_read(a, b, c)
- #define mp_exptmod(a,b,c,d) ltc_mp.exptmod(a,b,c,d)
- #endif
- int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
- {
- hash_state md;
- size_t i;
- md4_init(&md);
- for (i = 0; i < num_elem; i++)
- md4_process(&md, addr[i], len[i]);
- md4_done(&md, mac);
- return 0;
- }
- void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
- {
- u8 pkey[8], next, tmp;
- int i;
- symmetric_key skey;
-
- next = 0;
- for (i = 0; i < 7; i++) {
- tmp = key[i];
- pkey[i] = (tmp >> i) | next | 1;
- next = tmp << (7 - i);
- }
- pkey[i] = next | 1;
- des_setup(pkey, 8, 0, &skey);
- des_ecb_encrypt(clear, cypher, &skey);
- des_done(&skey);
- }
- int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
- {
- hash_state md;
- size_t i;
- md5_init(&md);
- for (i = 0; i < num_elem; i++)
- md5_process(&md, addr[i], len[i]);
- md5_done(&md, mac);
- return 0;
- }
- int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
- {
- hash_state md;
- size_t i;
- sha1_init(&md);
- for (i = 0; i < num_elem; i++)
- sha1_process(&md, addr[i], len[i]);
- sha1_done(&md, mac);
- return 0;
- }
- void * aes_encrypt_init(const u8 *key, size_t len)
- {
- symmetric_key *skey;
- skey = os_malloc(sizeof(*skey));
- if (skey == NULL)
- return NULL;
- if (aes_setup(key, len, 0, skey) != CRYPT_OK) {
- os_free(skey);
- return NULL;
- }
- return skey;
- }
- void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
- {
- symmetric_key *skey = ctx;
- aes_ecb_encrypt(plain, crypt, skey);
- }
- void aes_encrypt_deinit(void *ctx)
- {
- symmetric_key *skey = ctx;
- aes_done(skey);
- os_free(skey);
- }
- void * aes_decrypt_init(const u8 *key, size_t len)
- {
- symmetric_key *skey;
- skey = os_malloc(sizeof(*skey));
- if (skey == NULL)
- return NULL;
- if (aes_setup(key, len, 0, skey) != CRYPT_OK) {
- os_free(skey);
- return NULL;
- }
- return skey;
- }
- void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
- {
- symmetric_key *skey = ctx;
- aes_ecb_encrypt(plain, (u8 *) crypt, skey);
- }
- void aes_decrypt_deinit(void *ctx)
- {
- symmetric_key *skey = ctx;
- aes_done(skey);
- os_free(skey);
- }
- struct crypto_hash {
- enum crypto_hash_alg alg;
- int error;
- union {
- hash_state md;
- hmac_state hmac;
- } u;
- };
- struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
- size_t key_len)
- {
- struct crypto_hash *ctx;
- ctx = os_zalloc(sizeof(*ctx));
- if (ctx == NULL)
- return NULL;
- ctx->alg = alg;
- switch (alg) {
- case CRYPTO_HASH_ALG_MD5:
- if (md5_init(&ctx->u.md) != CRYPT_OK)
- goto fail;
- break;
- case CRYPTO_HASH_ALG_SHA1:
- if (sha1_init(&ctx->u.md) != CRYPT_OK)
- goto fail;
- break;
- case CRYPTO_HASH_ALG_HMAC_MD5:
- if (hmac_init(&ctx->u.hmac, find_hash("md5"), key, key_len) !=
- CRYPT_OK)
- goto fail;
- break;
- case CRYPTO_HASH_ALG_HMAC_SHA1:
- if (hmac_init(&ctx->u.hmac, find_hash("sha1"), key, key_len) !=
- CRYPT_OK)
- goto fail;
- break;
- default:
- goto fail;
- }
- return ctx;
- fail:
- os_free(ctx);
- return NULL;
- }
- void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
- {
- if (ctx == NULL || ctx->error)
- return;
- switch (ctx->alg) {
- case CRYPTO_HASH_ALG_MD5:
- ctx->error = md5_process(&ctx->u.md, data, len) != CRYPT_OK;
- break;
- case CRYPTO_HASH_ALG_SHA1:
- ctx->error = sha1_process(&ctx->u.md, data, len) != CRYPT_OK;
- break;
- case CRYPTO_HASH_ALG_HMAC_MD5:
- case CRYPTO_HASH_ALG_HMAC_SHA1:
- ctx->error = hmac_process(&ctx->u.hmac, data, len) != CRYPT_OK;
- break;
- }
- }
- int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
- {
- int ret = 0;
- unsigned long clen;
- if (ctx == NULL)
- return -2;
- if (mac == NULL || len == NULL) {
- os_free(ctx);
- return 0;
- }
- if (ctx->error) {
- os_free(ctx);
- return -2;
- }
- switch (ctx->alg) {
- case CRYPTO_HASH_ALG_MD5:
- if (*len < 16) {
- *len = 16;
- os_free(ctx);
- return -1;
- }
- *len = 16;
- if (md5_done(&ctx->u.md, mac) != CRYPT_OK)
- ret = -2;
- break;
- case CRYPTO_HASH_ALG_SHA1:
- if (*len < 20) {
- *len = 20;
- os_free(ctx);
- return -1;
- }
- *len = 20;
- if (sha1_done(&ctx->u.md, mac) != CRYPT_OK)
- ret = -2;
- break;
- case CRYPTO_HASH_ALG_HMAC_SHA1:
- if (*len < 20) {
- *len = 20;
- os_free(ctx);
- return -1;
- }
-
- case CRYPTO_HASH_ALG_HMAC_MD5:
- if (*len < 16) {
- *len = 16;
- os_free(ctx);
- return -1;
- }
- clen = *len;
- if (hmac_done(&ctx->u.hmac, mac, &clen) != CRYPT_OK) {
- os_free(ctx);
- return -1;
- }
- *len = clen;
- break;
- default:
- ret = -2;
- break;
- }
- os_free(ctx);
- return ret;
- }
- struct crypto_cipher {
- int rc4;
- union {
- symmetric_CBC cbc;
- struct {
- size_t used_bytes;
- u8 key[16];
- size_t keylen;
- } rc4;
- } u;
- };
- struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
- const u8 *iv, const u8 *key,
- size_t key_len)
- {
- struct crypto_cipher *ctx;
- int idx, res, rc4 = 0;
- switch (alg) {
- case CRYPTO_CIPHER_ALG_AES:
- idx = find_cipher("aes");
- break;
- case CRYPTO_CIPHER_ALG_3DES:
- idx = find_cipher("3des");
- break;
- case CRYPTO_CIPHER_ALG_DES:
- idx = find_cipher("des");
- break;
- case CRYPTO_CIPHER_ALG_RC2:
- idx = find_cipher("rc2");
- break;
- case CRYPTO_CIPHER_ALG_RC4:
- idx = -1;
- rc4 = 1;
- break;
- default:
- return NULL;
- }
- ctx = os_zalloc(sizeof(*ctx));
- if (ctx == NULL)
- return NULL;
- if (rc4) {
- ctx->rc4 = 1;
- if (key_len > sizeof(ctx->u.rc4.key)) {
- os_free(ctx);
- return NULL;
- }
- ctx->u.rc4.keylen = key_len;
- os_memcpy(ctx->u.rc4.key, key, key_len);
- } else {
- res = cbc_start(idx, iv, key, key_len, 0, &ctx->u.cbc);
- if (res != CRYPT_OK) {
- wpa_printf(MSG_DEBUG, "LibTomCrypt: Cipher start "
- "failed: %s", error_to_string(res));
- os_free(ctx);
- return NULL;
- }
- }
- return ctx;
- }
- int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
- u8 *crypt, size_t len)
- {
- int res;
- if (ctx->rc4) {
- if (plain != crypt)
- os_memcpy(crypt, plain, len);
- rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
- ctx->u.rc4.used_bytes, crypt, len);
- ctx->u.rc4.used_bytes += len;
- return 0;
- }
- res = cbc_encrypt(plain, crypt, len, &ctx->u.cbc);
- if (res != CRYPT_OK) {
- wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC encryption "
- "failed: %s", error_to_string(res));
- return -1;
- }
- return 0;
- }
- int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
- u8 *plain, size_t len)
- {
- int res;
- if (ctx->rc4) {
- if (plain != crypt)
- os_memcpy(plain, crypt, len);
- rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
- ctx->u.rc4.used_bytes, plain, len);
- ctx->u.rc4.used_bytes += len;
- return 0;
- }
- res = cbc_decrypt(crypt, plain, len, &ctx->u.cbc);
- if (res != CRYPT_OK) {
- wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC decryption "
- "failed: %s", error_to_string(res));
- return -1;
- }
- return 0;
- }
- void crypto_cipher_deinit(struct crypto_cipher *ctx)
- {
- if (!ctx->rc4)
- cbc_done(&ctx->u.cbc);
- os_free(ctx);
- }
- struct crypto_public_key {
- rsa_key rsa;
- };
- struct crypto_private_key {
- rsa_key rsa;
- };
- struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len)
- {
- int res;
- struct crypto_public_key *pk;
- pk = os_zalloc(sizeof(*pk));
- if (pk == NULL)
- return NULL;
- res = rsa_import(key, len, &pk->rsa);
- if (res != CRYPT_OK) {
- wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import "
- "public key (res=%d '%s')",
- res, error_to_string(res));
- os_free(pk);
- return NULL;
- }
- if (pk->rsa.type != PK_PUBLIC) {
- wpa_printf(MSG_ERROR, "LibTomCrypt: Public key was not of "
- "correct type");
- rsa_free(&pk->rsa);
- os_free(pk);
- return NULL;
- }
- return pk;
- }
- struct crypto_private_key * crypto_private_key_import(const u8 *key,
- size_t len,
- const char *passwd)
- {
- int res;
- struct crypto_private_key *pk;
- pk = os_zalloc(sizeof(*pk));
- if (pk == NULL)
- return NULL;
- res = rsa_import(key, len, &pk->rsa);
- if (res != CRYPT_OK) {
- wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import "
- "private key (res=%d '%s')",
- res, error_to_string(res));
- os_free(pk);
- return NULL;
- }
- if (pk->rsa.type != PK_PRIVATE) {
- wpa_printf(MSG_ERROR, "LibTomCrypt: Private key was not of "
- "correct type");
- rsa_free(&pk->rsa);
- os_free(pk);
- return NULL;
- }
- return pk;
- }
- struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf,
- size_t len)
- {
-
- return NULL;
- }
- static int pkcs1_generate_encryption_block(u8 block_type, size_t modlen,
- const u8 *in, size_t inlen,
- u8 *out, size_t *outlen)
- {
- size_t ps_len;
- u8 *pos;
-
- if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) {
- wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer "
- "lengths (modlen=%lu outlen=%lu inlen=%lu)",
- __func__, (unsigned long) modlen,
- (unsigned long) *outlen,
- (unsigned long) inlen);
- return -1;
- }
- pos = out;
- *pos++ = 0x00;
- *pos++ = block_type;
- ps_len = modlen - inlen - 3;
- switch (block_type) {
- case 0:
- os_memset(pos, 0x00, ps_len);
- pos += ps_len;
- break;
- case 1:
- os_memset(pos, 0xff, ps_len);
- pos += ps_len;
- break;
- case 2:
- if (os_get_random(pos, ps_len) < 0) {
- wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get "
- "random data for PS", __func__);
- return -1;
- }
- while (ps_len--) {
- if (*pos == 0x00)
- *pos = 0x01;
- pos++;
- }
- break;
- default:
- wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type "
- "%d", __func__, block_type);
- return -1;
- }
- *pos++ = 0x00;
- os_memcpy(pos, in, inlen);
- return 0;
- }
- static int crypto_rsa_encrypt_pkcs1(int block_type, rsa_key *key, int key_type,
- const u8 *in, size_t inlen,
- u8 *out, size_t *outlen)
- {
- unsigned long len, modlen;
- int res;
- modlen = mp_unsigned_bin_size(key->N);
- if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen,
- out, outlen) < 0)
- return -1;
- len = *outlen;
- res = rsa_exptmod(out, modlen, out, &len, key_type, key);
- if (res != CRYPT_OK) {
- wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s",
- error_to_string(res));
- return -1;
- }
- *outlen = len;
- return 0;
- }
- int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key,
- const u8 *in, size_t inlen,
- u8 *out, size_t *outlen)
- {
- return crypto_rsa_encrypt_pkcs1(2, &key->rsa, PK_PUBLIC, in, inlen,
- out, outlen);
- }
- int crypto_private_key_sign_pkcs1(struct crypto_private_key *key,
- const u8 *in, size_t inlen,
- u8 *out, size_t *outlen)
- {
- return crypto_rsa_encrypt_pkcs1(1, &key->rsa, PK_PRIVATE, in, inlen,
- out, outlen);
- }
- void crypto_public_key_free(struct crypto_public_key *key)
- {
- if (key) {
- rsa_free(&key->rsa);
- os_free(key);
- }
- }
- void crypto_private_key_free(struct crypto_private_key *key)
- {
- if (key) {
- rsa_free(&key->rsa);
- os_free(key);
- }
- }
- int crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key,
- const u8 *crypt, size_t crypt_len,
- u8 *plain, size_t *plain_len)
- {
- int res;
- unsigned long len;
- u8 *pos;
- len = *plain_len;
- res = rsa_exptmod(crypt, crypt_len, plain, &len, PK_PUBLIC,
- &key->rsa);
- if (res != CRYPT_OK) {
- wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s",
- error_to_string(res));
- return -1;
- }
-
- if (len < 3 + 8 + 16 ||
- plain[0] != 0x00 || plain[1] != 0x01 || plain[2] != 0xff) {
- wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
- "structure");
- return -1;
- }
- pos = plain + 3;
- while (pos < plain + len && *pos == 0xff)
- pos++;
- if (pos - plain - 2 < 8) {
-
- wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature "
- "padding");
- return -1;
- }
- if (pos + 16 >= plain + len || *pos != 0x00) {
- wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
- "structure (2)");
- return -1;
- }
- pos++;
- len -= pos - plain;
-
- os_memmove(plain, pos, len);
- *plain_len = len;
- return 0;
- }
- int crypto_global_init(void)
- {
- ltc_mp = tfm_desc;
-
- if (register_hash(&md4_desc) < 0 ||
- register_hash(&md5_desc) < 0 ||
- register_hash(&sha1_desc) < 0 ||
- register_cipher(&aes_desc) < 0 ||
- register_cipher(&des_desc) < 0 ||
- register_cipher(&des3_desc) < 0) {
- wpa_printf(MSG_ERROR, "TLSv1: Failed to register "
- "hash/cipher functions");
- return -1;
- }
- return 0;
- }
- void crypto_global_deinit(void)
- {
- }
- #ifdef CONFIG_MODEXP
- int 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)
- {
- void *b, *p, *m, *r;
- if (mp_init_multi(&b, &p, &m, &r, NULL) != CRYPT_OK)
- return -1;
- if (mp_read_unsigned_bin(b, (u8 *) base, base_len) != CRYPT_OK ||
- mp_read_unsigned_bin(p, (u8 *) power, power_len) != CRYPT_OK ||
- mp_read_unsigned_bin(m, (u8 *) modulus, modulus_len) != CRYPT_OK)
- goto fail;
- if (mp_exptmod(b, p, m, r) != CRYPT_OK)
- goto fail;
- *result_len = mp_unsigned_bin_size(r);
- if (mp_to_unsigned_bin(r, result) != CRYPT_OK)
- goto fail;
- mp_clear_multi(b, p, m, r, NULL);
- return 0;
- fail:
- mp_clear_multi(b, p, m, r, NULL);
- return -1;
- }
- #endif
|