crypto_libtomcrypt.c revision 189251
1178784Skmacy/* 2178784Skmacy * WPA Supplicant / Crypto wrapper for LibTomCrypt (for internal TLSv1) 3178784Skmacy * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> 4178784Skmacy * 5178784Skmacy * This program is free software; you can redistribute it and/or modify 6178784Skmacy * it under the terms of the GNU General Public License version 2 as 7178784Skmacy * published by the Free Software Foundation. 8178784Skmacy * 9178784Skmacy * Alternatively, this software may be distributed under the terms of BSD 10178784Skmacy * license. 11178784Skmacy * 12178784Skmacy * See README and COPYING for more details. 13178784Skmacy */ 14178784Skmacy 15178784Skmacy#include "includes.h" 16178784Skmacy#include <tomcrypt.h> 17178784Skmacy 18178784Skmacy#include "common.h" 19178784Skmacy#include "rc4.h" 20178784Skmacy#include "crypto.h" 21178784Skmacy 22178784Skmacy#ifndef mp_init_multi 23178784Skmacy#define mp_init_multi ltc_init_multi 24178784Skmacy#define mp_clear_multi ltc_deinit_multi 25178784Skmacy#define mp_unsigned_bin_size(a) ltc_mp.unsigned_size(a) 26178784Skmacy#define mp_to_unsigned_bin(a, b) ltc_mp.unsigned_write(a, b) 27178784Skmacy#define mp_read_unsigned_bin(a, b, c) ltc_mp.unsigned_read(a, b, c) 28178784Skmacy#define mp_exptmod(a,b,c,d) ltc_mp.exptmod(a,b,c,d) 29178784Skmacy#endif 30178784Skmacy 31178784Skmacy 32178784Skmacyvoid md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 33178784Skmacy{ 34178784Skmacy hash_state md; 35178784Skmacy size_t i; 36178784Skmacy 37178784Skmacy md4_init(&md); 38178784Skmacy for (i = 0; i < num_elem; i++) 39178784Skmacy md4_process(&md, addr[i], len[i]); 40178784Skmacy md4_done(&md, mac); 41178784Skmacy} 42178784Skmacy 43178784Skmacy 44178784Skmacyvoid des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) 45178784Skmacy{ 46178784Skmacy u8 pkey[8], next, tmp; 47178784Skmacy int i; 48178784Skmacy symmetric_key skey; 49178784Skmacy 50178784Skmacy /* Add parity bits to the key */ 51178784Skmacy next = 0; 52178784Skmacy for (i = 0; i < 7; i++) { 53178784Skmacy tmp = key[i]; 54178784Skmacy pkey[i] = (tmp >> i) | next | 1; 55178784Skmacy next = tmp << (7 - i); 56178784Skmacy } 57178784Skmacy pkey[i] = next | 1; 58178784Skmacy 59178784Skmacy des_setup(pkey, 8, 0, &skey); 60178784Skmacy des_ecb_encrypt(clear, cypher, &skey); 61178784Skmacy des_done(&skey); 62178784Skmacy} 63178784Skmacy 64178784Skmacy 65178784Skmacy#ifdef EAP_TLS_FUNCS 66178784Skmacyvoid md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 67178784Skmacy{ 68178784Skmacy hash_state md; 69178784Skmacy size_t i; 70178784Skmacy 71178784Skmacy md5_init(&md); 72178784Skmacy for (i = 0; i < num_elem; i++) 73178784Skmacy md5_process(&md, addr[i], len[i]); 74178784Skmacy md5_done(&md, mac); 75178784Skmacy} 76178784Skmacy 77178784Skmacy 78178784Skmacyvoid sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 79178784Skmacy{ 80178784Skmacy hash_state md; 81178784Skmacy size_t i; 82178784Skmacy 83178784Skmacy sha1_init(&md); 84178784Skmacy for (i = 0; i < num_elem; i++) 85178784Skmacy sha1_process(&md, addr[i], len[i]); 86178784Skmacy sha1_done(&md, mac); 87178784Skmacy} 88178784Skmacy 89178784Skmacy 90178784Skmacyvoid * aes_encrypt_init(const u8 *key, size_t len) 91178784Skmacy{ 92178784Skmacy symmetric_key *skey; 93178784Skmacy skey = os_malloc(sizeof(*skey)); 94178784Skmacy if (skey == NULL) 95178784Skmacy return NULL; 96178784Skmacy if (aes_setup(key, len, 0, skey) != CRYPT_OK) { 97178784Skmacy os_free(skey); 98178784Skmacy return NULL; 99178784Skmacy } 100178784Skmacy return skey; 101178784Skmacy} 102178784Skmacy 103178784Skmacy 104178784Skmacyvoid aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) 105178784Skmacy{ 106178784Skmacy symmetric_key *skey = ctx; 107178784Skmacy aes_ecb_encrypt(plain, crypt, skey); 108178784Skmacy} 109178784Skmacy 110178784Skmacy 111178784Skmacyvoid aes_encrypt_deinit(void *ctx) 112178784Skmacy{ 113178784Skmacy symmetric_key *skey = ctx; 114178784Skmacy aes_done(skey); 115178784Skmacy os_free(skey); 116178784Skmacy} 117178784Skmacy 118178784Skmacy 119178784Skmacyvoid * aes_decrypt_init(const u8 *key, size_t len) 120178784Skmacy{ 121178784Skmacy symmetric_key *skey; 122178784Skmacy skey = os_malloc(sizeof(*skey)); 123178784Skmacy if (skey == NULL) 124178784Skmacy return NULL; 125178784Skmacy if (aes_setup(key, len, 0, skey) != CRYPT_OK) { 126178784Skmacy os_free(skey); 127178784Skmacy return NULL; 128178784Skmacy } 129178784Skmacy return skey; 130178784Skmacy} 131178784Skmacy 132178784Skmacy 133178784Skmacyvoid aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) 134178784Skmacy{ 135178784Skmacy symmetric_key *skey = ctx; 136178784Skmacy aes_ecb_encrypt(plain, (u8 *) crypt, skey); 137178784Skmacy} 138178784Skmacy 139178784Skmacy 140178784Skmacyvoid aes_decrypt_deinit(void *ctx) 141178784Skmacy{ 142178784Skmacy symmetric_key *skey = ctx; 143178784Skmacy aes_done(skey); 144178784Skmacy os_free(skey); 145178784Skmacy} 146178784Skmacy 147178784Skmacy 148178784Skmacy#ifdef CONFIG_TLS_INTERNAL 149178784Skmacy 150178784Skmacystruct crypto_hash { 151178784Skmacy enum crypto_hash_alg alg; 152178784Skmacy int error; 153178784Skmacy union { 154178784Skmacy hash_state md; 155178784Skmacy hmac_state hmac; 156178784Skmacy } u; 157178784Skmacy}; 158178784Skmacy 159178784Skmacy 160178784Skmacystruct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, 161178784Skmacy size_t key_len) 162178784Skmacy{ 163178784Skmacy struct crypto_hash *ctx; 164178784Skmacy 165178784Skmacy ctx = os_zalloc(sizeof(*ctx)); 166178784Skmacy if (ctx == NULL) 167178784Skmacy return NULL; 168178784Skmacy 169178784Skmacy ctx->alg = alg; 170178784Skmacy 171178784Skmacy switch (alg) { 172178784Skmacy case CRYPTO_HASH_ALG_MD5: 173178784Skmacy if (md5_init(&ctx->u.md) != CRYPT_OK) 174178784Skmacy goto fail; 175178784Skmacy break; 176178784Skmacy case CRYPTO_HASH_ALG_SHA1: 177178784Skmacy if (sha1_init(&ctx->u.md) != CRYPT_OK) 178178784Skmacy goto fail; 179178784Skmacy break; 180178784Skmacy case CRYPTO_HASH_ALG_HMAC_MD5: 181178784Skmacy if (hmac_init(&ctx->u.hmac, find_hash("md5"), key, key_len) != 182178784Skmacy CRYPT_OK) 183178784Skmacy goto fail; 184178784Skmacy break; 185178784Skmacy case CRYPTO_HASH_ALG_HMAC_SHA1: 186178784Skmacy if (hmac_init(&ctx->u.hmac, find_hash("sha1"), key, key_len) != 187178784Skmacy CRYPT_OK) 188178784Skmacy goto fail; 189178784Skmacy break; 190178784Skmacy default: 191178784Skmacy goto fail; 192178784Skmacy } 193178784Skmacy 194178784Skmacy return ctx; 195178784Skmacy 196178784Skmacyfail: 197178784Skmacy os_free(ctx); 198178784Skmacy return NULL; 199178784Skmacy} 200178784Skmacy 201178784Skmacyvoid crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) 202178784Skmacy{ 203178784Skmacy if (ctx == NULL || ctx->error) 204178784Skmacy return; 205178784Skmacy 206178784Skmacy switch (ctx->alg) { 207178784Skmacy case CRYPTO_HASH_ALG_MD5: 208178784Skmacy ctx->error = md5_process(&ctx->u.md, data, len) != CRYPT_OK; 209178784Skmacy break; 210178784Skmacy case CRYPTO_HASH_ALG_SHA1: 211178784Skmacy ctx->error = sha1_process(&ctx->u.md, data, len) != CRYPT_OK; 212178784Skmacy break; 213178784Skmacy case CRYPTO_HASH_ALG_HMAC_MD5: 214178784Skmacy case CRYPTO_HASH_ALG_HMAC_SHA1: 215178784Skmacy ctx->error = hmac_process(&ctx->u.hmac, data, len) != CRYPT_OK; 216178784Skmacy break; 217178784Skmacy } 218178784Skmacy} 219178784Skmacy 220178784Skmacy 221178784Skmacyint crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) 222178784Skmacy{ 223178784Skmacy int ret = 0; 224178784Skmacy unsigned long clen; 225178784Skmacy 226178784Skmacy if (ctx == NULL) 227178784Skmacy return -2; 228178784Skmacy 229178784Skmacy if (mac == NULL || len == NULL) { 230178784Skmacy os_free(ctx); 231178784Skmacy return 0; 232178784Skmacy } 233178784Skmacy 234178784Skmacy if (ctx->error) { 235178784Skmacy os_free(ctx); 236178784Skmacy return -2; 237178784Skmacy } 238178784Skmacy 239178784Skmacy switch (ctx->alg) { 240178784Skmacy case CRYPTO_HASH_ALG_MD5: 241178784Skmacy if (*len < 16) { 242178784Skmacy *len = 16; 243178784Skmacy os_free(ctx); 244178784Skmacy return -1; 245178784Skmacy } 246178784Skmacy *len = 16; 247178784Skmacy if (md5_done(&ctx->u.md, mac) != CRYPT_OK) 248178784Skmacy ret = -2; 249178784Skmacy break; 250178784Skmacy case CRYPTO_HASH_ALG_SHA1: 251178784Skmacy if (*len < 20) { 252178784Skmacy *len = 20; 253178784Skmacy os_free(ctx); 254178784Skmacy return -1; 255178784Skmacy } 256178784Skmacy *len = 20; 257178784Skmacy if (sha1_done(&ctx->u.md, mac) != CRYPT_OK) 258178784Skmacy ret = -2; 259178784Skmacy break; 260178784Skmacy case CRYPTO_HASH_ALG_HMAC_SHA1: 261178784Skmacy if (*len < 20) { 262178784Skmacy *len = 20; 263178784Skmacy os_free(ctx); 264178784Skmacy return -1; 265178784Skmacy } 266178784Skmacy /* continue */ 267178784Skmacy case CRYPTO_HASH_ALG_HMAC_MD5: 268178784Skmacy if (*len < 16) { 269178784Skmacy *len = 16; 270178784Skmacy os_free(ctx); 271178784Skmacy return -1; 272178784Skmacy } 273178784Skmacy clen = *len; 274178784Skmacy if (hmac_done(&ctx->u.hmac, mac, &clen) != CRYPT_OK) { 275178784Skmacy os_free(ctx); 276178784Skmacy return -1; 277178784Skmacy } 278178784Skmacy *len = clen; 279178784Skmacy break; 280178784Skmacy default: 281178784Skmacy ret = -2; 282178784Skmacy break; 283178784Skmacy } 284178784Skmacy 285178784Skmacy os_free(ctx); 286178784Skmacy 287178784Skmacy return ret; 288178784Skmacy} 289178784Skmacy 290178784Skmacy 291178784Skmacystruct crypto_cipher { 292178784Skmacy int rc4; 293178784Skmacy union { 294178784Skmacy symmetric_CBC cbc; 295178784Skmacy struct { 296178784Skmacy size_t used_bytes; 297178784Skmacy u8 key[16]; 298178784Skmacy size_t keylen; 299178784Skmacy } rc4; 300178784Skmacy } u; 301178784Skmacy}; 302178784Skmacy 303178784Skmacy 304178784Skmacystruct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, 305178784Skmacy const u8 *iv, const u8 *key, 306178784Skmacy size_t key_len) 307178784Skmacy{ 308178784Skmacy struct crypto_cipher *ctx; 309178784Skmacy int idx, res, rc4 = 0; 310178784Skmacy 311178784Skmacy switch (alg) { 312178784Skmacy case CRYPTO_CIPHER_ALG_AES: 313178784Skmacy idx = find_cipher("aes"); 314178784Skmacy break; 315178784Skmacy case CRYPTO_CIPHER_ALG_3DES: 316178784Skmacy idx = find_cipher("3des"); 317178784Skmacy break; 318178784Skmacy case CRYPTO_CIPHER_ALG_DES: 319178784Skmacy idx = find_cipher("des"); 320178784Skmacy break; 321178784Skmacy case CRYPTO_CIPHER_ALG_RC2: 322178784Skmacy idx = find_cipher("rc2"); 323178784Skmacy break; 324178784Skmacy case CRYPTO_CIPHER_ALG_RC4: 325178784Skmacy idx = -1; 326178784Skmacy rc4 = 1; 327178784Skmacy break; 328178784Skmacy default: 329178784Skmacy return NULL; 330178784Skmacy } 331178784Skmacy 332178784Skmacy ctx = os_zalloc(sizeof(*ctx)); 333178784Skmacy if (ctx == NULL) 334178784Skmacy return NULL; 335178784Skmacy 336178784Skmacy if (rc4) { 337178784Skmacy ctx->rc4 = 1; 338178784Skmacy if (key_len > sizeof(ctx->u.rc4.key)) { 339178784Skmacy os_free(ctx); 340178784Skmacy return NULL; 341178784Skmacy } 342178784Skmacy ctx->u.rc4.keylen = key_len; 343178784Skmacy os_memcpy(ctx->u.rc4.key, key, key_len); 344178784Skmacy } else { 345178784Skmacy res = cbc_start(idx, iv, key, key_len, 0, &ctx->u.cbc); 346178784Skmacy if (res != CRYPT_OK) { 347178784Skmacy wpa_printf(MSG_DEBUG, "LibTomCrypt: Cipher start " 348178784Skmacy "failed: %s", error_to_string(res)); 349178784Skmacy os_free(ctx); 350178784Skmacy return NULL; 351178784Skmacy } 352178784Skmacy } 353178784Skmacy 354178784Skmacy return ctx; 355178784Skmacy} 356178784Skmacy 357178784Skmacyint crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, 358178784Skmacy u8 *crypt, size_t len) 359178784Skmacy{ 360178784Skmacy int res; 361178784Skmacy 362178784Skmacy if (ctx->rc4) { 363178784Skmacy if (plain != crypt) 364178784Skmacy os_memcpy(crypt, plain, len); 365178784Skmacy rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, 366178784Skmacy ctx->u.rc4.used_bytes, crypt, len); 367178784Skmacy ctx->u.rc4.used_bytes += len; 368178784Skmacy return 0; 369178784Skmacy } 370178784Skmacy 371178784Skmacy res = cbc_encrypt(plain, crypt, len, &ctx->u.cbc); 372178784Skmacy if (res != CRYPT_OK) { 373178784Skmacy wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC encryption " 374178784Skmacy "failed: %s", error_to_string(res)); 375178784Skmacy return -1; 376178784Skmacy } 377178784Skmacy return 0; 378178784Skmacy} 379178784Skmacy 380178784Skmacy 381178784Skmacyint crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, 382178784Skmacy u8 *plain, size_t len) 383178784Skmacy{ 384178784Skmacy int res; 385178784Skmacy 386178784Skmacy if (ctx->rc4) { 387178784Skmacy if (plain != crypt) 388178784Skmacy os_memcpy(plain, crypt, len); 389178784Skmacy rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, 390178784Skmacy ctx->u.rc4.used_bytes, plain, len); 391178784Skmacy ctx->u.rc4.used_bytes += len; 392178784Skmacy return 0; 393178784Skmacy } 394178784Skmacy 395178784Skmacy res = cbc_decrypt(crypt, plain, len, &ctx->u.cbc); 396178784Skmacy if (res != CRYPT_OK) { 397178784Skmacy wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC decryption " 398178784Skmacy "failed: %s", error_to_string(res)); 399178784Skmacy return -1; 400178784Skmacy } 401178784Skmacy 402178784Skmacy return 0; 403178784Skmacy} 404178784Skmacy 405178784Skmacy 406178784Skmacyvoid crypto_cipher_deinit(struct crypto_cipher *ctx) 407178784Skmacy{ 408178784Skmacy if (!ctx->rc4) 409178784Skmacy cbc_done(&ctx->u.cbc); 410178784Skmacy os_free(ctx); 411178784Skmacy} 412178784Skmacy 413178784Skmacy 414178784Skmacystruct crypto_public_key { 415178784Skmacy rsa_key rsa; 416178784Skmacy}; 417178784Skmacy 418178784Skmacystruct crypto_private_key { 419178784Skmacy rsa_key rsa; 420178784Skmacy}; 421178784Skmacy 422178784Skmacy 423178784Skmacystruct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len) 424178784Skmacy{ 425178784Skmacy int res; 426178784Skmacy struct crypto_public_key *pk; 427178784Skmacy 428178784Skmacy pk = os_zalloc(sizeof(*pk)); 429178784Skmacy if (pk == NULL) 430178784Skmacy return NULL; 431178784Skmacy 432178784Skmacy res = rsa_import(key, len, &pk->rsa); 433178784Skmacy if (res != CRYPT_OK) { 434178784Skmacy wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import " 435178784Skmacy "public key (res=%d '%s')", 436178784Skmacy res, error_to_string(res)); 437178784Skmacy os_free(pk); 438178784Skmacy return NULL; 439178784Skmacy } 440178784Skmacy 441178784Skmacy if (pk->rsa.type != PK_PUBLIC) { 442178784Skmacy wpa_printf(MSG_ERROR, "LibTomCrypt: Public key was not of " 443178784Skmacy "correct type"); 444178784Skmacy rsa_free(&pk->rsa); 445178784Skmacy os_free(pk); 446178784Skmacy return NULL; 447178784Skmacy } 448178784Skmacy 449178784Skmacy return pk; 450178784Skmacy} 451178784Skmacy 452178784Skmacy 453178784Skmacystruct crypto_private_key * crypto_private_key_import(const u8 *key, 454178784Skmacy size_t len) 455178784Skmacy{ 456178784Skmacy int res; 457178784Skmacy struct crypto_private_key *pk; 458178784Skmacy 459178784Skmacy pk = os_zalloc(sizeof(*pk)); 460178784Skmacy if (pk == NULL) 461178784Skmacy return NULL; 462178784Skmacy 463178784Skmacy res = rsa_import(key, len, &pk->rsa); 464178784Skmacy if (res != CRYPT_OK) { 465178784Skmacy wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import " 466178784Skmacy "private key (res=%d '%s')", 467178784Skmacy res, error_to_string(res)); 468178784Skmacy os_free(pk); 469178784Skmacy return NULL; 470178784Skmacy } 471178784Skmacy 472178784Skmacy if (pk->rsa.type != PK_PRIVATE) { 473178784Skmacy wpa_printf(MSG_ERROR, "LibTomCrypt: Private key was not of " 474178784Skmacy "correct type"); 475178784Skmacy rsa_free(&pk->rsa); 476178784Skmacy os_free(pk); 477178784Skmacy return NULL; 478178784Skmacy } 479178784Skmacy 480178784Skmacy return pk; 481178784Skmacy} 482178784Skmacy 483178784Skmacy 484178784Skmacystruct crypto_public_key * crypto_public_key_from_cert(const u8 *buf, 485178784Skmacy size_t len) 486178784Skmacy{ 487178784Skmacy /* No X.509 support in LibTomCrypt */ 488178784Skmacy return NULL; 489178784Skmacy} 490178784Skmacy 491178784Skmacy 492178784Skmacystatic int pkcs1_generate_encryption_block(u8 block_type, size_t modlen, 493178784Skmacy const u8 *in, size_t inlen, 494178784Skmacy u8 *out, size_t *outlen) 495178784Skmacy{ 496178784Skmacy size_t ps_len; 497178784Skmacy u8 *pos; 498178784Skmacy 499178784Skmacy /* 500178784Skmacy * PKCS #1 v1.5, 8.1: 501178784Skmacy * 502178784Skmacy * EB = 00 || BT || PS || 00 || D 503178784Skmacy * BT = 00 or 01 for private-key operation; 02 for public-key operation 504178784Skmacy * PS = k-3-||D||; at least eight octets 505178784Skmacy * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero) 506178784Skmacy * k = length of modulus in octets (modlen) 507178784Skmacy */ 508178784Skmacy 509178784Skmacy if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) { 510178784Skmacy wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer " 511178784Skmacy "lengths (modlen=%lu outlen=%lu inlen=%lu)", 512178784Skmacy __func__, (unsigned long) modlen, 513178784Skmacy (unsigned long) *outlen, 514178784Skmacy (unsigned long) inlen); 515178784Skmacy return -1; 516178784Skmacy } 517178784Skmacy 518178784Skmacy pos = out; 519178784Skmacy *pos++ = 0x00; 520178784Skmacy *pos++ = block_type; /* BT */ 521178784Skmacy ps_len = modlen - inlen - 3; 522178784Skmacy switch (block_type) { 523178784Skmacy case 0: 524178784Skmacy os_memset(pos, 0x00, ps_len); 525178784Skmacy pos += ps_len; 526178784Skmacy break; 527178784Skmacy case 1: 528178784Skmacy os_memset(pos, 0xff, ps_len); 529178784Skmacy pos += ps_len; 530178784Skmacy break; 531178784Skmacy case 2: 532178784Skmacy if (os_get_random(pos, ps_len) < 0) { 533178784Skmacy wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get " 534178784Skmacy "random data for PS", __func__); 535178784Skmacy return -1; 536178784Skmacy } 537178784Skmacy while (ps_len--) { 538178784Skmacy if (*pos == 0x00) 539178784Skmacy *pos = 0x01; 540178784Skmacy pos++; 541178784Skmacy } 542178784Skmacy break; 543178784Skmacy default: 544178784Skmacy wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type " 545178784Skmacy "%d", __func__, block_type); 546178784Skmacy return -1; 547178784Skmacy } 548178784Skmacy *pos++ = 0x00; 549178784Skmacy os_memcpy(pos, in, inlen); /* D */ 550178784Skmacy 551178784Skmacy return 0; 552178784Skmacy} 553178784Skmacy 554178784Skmacy 555178784Skmacystatic int crypto_rsa_encrypt_pkcs1(int block_type, rsa_key *key, int key_type, 556178784Skmacy const u8 *in, size_t inlen, 557178784Skmacy u8 *out, size_t *outlen) 558178784Skmacy{ 559178784Skmacy unsigned long len, modlen; 560178784Skmacy int res; 561178784Skmacy 562178784Skmacy modlen = mp_unsigned_bin_size(key->N); 563178784Skmacy 564178784Skmacy if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen, 565178784Skmacy out, outlen) < 0) 566178784Skmacy return -1; 567178784Skmacy 568178784Skmacy len = *outlen; 569178784Skmacy res = rsa_exptmod(out, modlen, out, &len, key_type, key); 570178784Skmacy if (res != CRYPT_OK) { 571178784Skmacy wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s", 572178784Skmacy error_to_string(res)); 573178784Skmacy return -1; 574178784Skmacy } 575178784Skmacy *outlen = len; 576178784Skmacy 577178784Skmacy return 0; 578178784Skmacy} 579178784Skmacy 580178784Skmacy 581178784Skmacyint crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key, 582178784Skmacy const u8 *in, size_t inlen, 583178784Skmacy u8 *out, size_t *outlen) 584178784Skmacy{ 585178784Skmacy return crypto_rsa_encrypt_pkcs1(2, &key->rsa, PK_PUBLIC, in, inlen, 586178784Skmacy out, outlen); 587178784Skmacy} 588178784Skmacy 589178784Skmacy 590178784Skmacyint crypto_private_key_sign_pkcs1(struct crypto_private_key *key, 591178784Skmacy const u8 *in, size_t inlen, 592178784Skmacy u8 *out, size_t *outlen) 593178784Skmacy{ 594178784Skmacy return crypto_rsa_encrypt_pkcs1(1, &key->rsa, PK_PRIVATE, in, inlen, 595178784Skmacy out, outlen); 596178784Skmacy} 597178784Skmacy 598178784Skmacy 599178784Skmacyvoid crypto_public_key_free(struct crypto_public_key *key) 600178784Skmacy{ 601178784Skmacy if (key) { 602178784Skmacy rsa_free(&key->rsa); 603178784Skmacy os_free(key); 604178784Skmacy } 605178784Skmacy} 606178784Skmacy 607178784Skmacy 608178784Skmacyvoid crypto_private_key_free(struct crypto_private_key *key) 609178784Skmacy{ 610178784Skmacy if (key) { 611178784Skmacy rsa_free(&key->rsa); 612178784Skmacy os_free(key); 613178784Skmacy } 614178784Skmacy} 615178784Skmacy 616178784Skmacy 617178784Skmacyint crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key, 618178784Skmacy const u8 *crypt, size_t crypt_len, 619178784Skmacy u8 *plain, size_t *plain_len) 620178784Skmacy{ 621178784Skmacy int res; 622178784Skmacy unsigned long len; 623178784Skmacy u8 *pos; 624178784Skmacy 625178784Skmacy len = *plain_len; 626178784Skmacy res = rsa_exptmod(crypt, crypt_len, plain, &len, PK_PUBLIC, 627178784Skmacy &key->rsa); 628178784Skmacy if (res != CRYPT_OK) { 629178784Skmacy wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s", 630178784Skmacy error_to_string(res)); 631178784Skmacy return -1; 632178784Skmacy } 633178784Skmacy 634178784Skmacy /* 635178784Skmacy * PKCS #1 v1.5, 8.1: 636178784Skmacy * 637178784Skmacy * EB = 00 || BT || PS || 00 || D 638178784Skmacy * BT = 01 639178784Skmacy * PS = k-3-||D|| times FF 640178784Skmacy * k = length of modulus in octets 641178784Skmacy */ 642178784Skmacy 643178784Skmacy if (len < 3 + 8 + 16 /* min hash len */ || 644178784Skmacy plain[0] != 0x00 || plain[1] != 0x01 || plain[2] != 0xff) { 645178784Skmacy wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " 646178784Skmacy "structure"); 647178784Skmacy return -1; 648178784Skmacy } 649178784Skmacy 650178784Skmacy pos = plain + 3; 651178784Skmacy while (pos < plain + len && *pos == 0xff) 652178784Skmacy pos++; 653178784Skmacy if (pos - plain - 2 < 8) { 654178784Skmacy /* PKCS #1 v1.5, 8.1: At least eight octets long PS */ 655178784Skmacy wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature " 656178784Skmacy "padding"); 657178784Skmacy return -1; 658178784Skmacy } 659178784Skmacy 660178784Skmacy if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) { 661178784Skmacy wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " 662178784Skmacy "structure (2)"); 663178784Skmacy return -1; 664178784Skmacy } 665178784Skmacy pos++; 666178784Skmacy len -= pos - plain; 667178784Skmacy 668178784Skmacy /* Strip PKCS #1 header */ 669178784Skmacy os_memmove(plain, pos, len); 670178784Skmacy *plain_len = len; 671178784Skmacy 672178784Skmacy return 0; 673178784Skmacy} 674178784Skmacy 675178784Skmacy 676178784Skmacyint crypto_global_init(void) 677178784Skmacy{ 678178784Skmacy ltc_mp = tfm_desc; 679178784Skmacy /* TODO: only register algorithms that are really needed */ 680178784Skmacy if (register_hash(&md4_desc) < 0 || 681178784Skmacy register_hash(&md5_desc) < 0 || 682178784Skmacy register_hash(&sha1_desc) < 0 || 683178784Skmacy register_cipher(&aes_desc) < 0 || 684178784Skmacy register_cipher(&des_desc) < 0 || 685178784Skmacy register_cipher(&des3_desc) < 0) { 686178784Skmacy wpa_printf(MSG_ERROR, "TLSv1: Failed to register " 687178784Skmacy "hash/cipher functions"); 688178784Skmacy return -1; 689178784Skmacy } 690178784Skmacy 691178784Skmacy return 0; 692178784Skmacy} 693178784Skmacy 694178784Skmacy 695178784Skmacyvoid crypto_global_deinit(void) 696178784Skmacy{ 697178784Skmacy} 698178784Skmacy 699178784Skmacy 700178784Skmacy#ifdef EAP_FAST 701178784Skmacy 702178784Skmacyint crypto_mod_exp(const u8 *base, size_t base_len, 703178784Skmacy const u8 *power, size_t power_len, 704178784Skmacy const u8 *modulus, size_t modulus_len, 705178784Skmacy u8 *result, size_t *result_len) 706178784Skmacy{ 707178784Skmacy void *b, *p, *m, *r; 708178784Skmacy 709178784Skmacy if (mp_init_multi(&b, &p, &m, &r, NULL) != CRYPT_OK) 710178784Skmacy return -1; 711178784Skmacy 712178784Skmacy if (mp_read_unsigned_bin(b, (u8 *) base, base_len) != CRYPT_OK || 713178784Skmacy mp_read_unsigned_bin(p, (u8 *) power, power_len) != CRYPT_OK || 714178784Skmacy mp_read_unsigned_bin(m, (u8 *) modulus, modulus_len) != CRYPT_OK) 715178784Skmacy goto fail; 716178784Skmacy 717178784Skmacy if (mp_exptmod(b, p, m, r) != CRYPT_OK) 718178784Skmacy goto fail; 719178784Skmacy 720178784Skmacy *result_len = mp_unsigned_bin_size(r); 721178784Skmacy if (mp_to_unsigned_bin(r, result) != CRYPT_OK) 722178784Skmacy goto fail; 723178784Skmacy 724178784Skmacy mp_clear_multi(b, p, m, r, NULL); 725178784Skmacy return 0; 726178784Skmacy 727178784Skmacyfail: 728178784Skmacy mp_clear_multi(b, p, m, r, NULL); 729178784Skmacy return -1; 730178784Skmacy} 731178784Skmacy 732178784Skmacy#endif /* EAP_FAST */ 733178784Skmacy 734178784Skmacy#endif /* CONFIG_TLS_INTERNAL */ 735178784Skmacy 736178784Skmacy#endif /* EAP_TLS_FUNCS */ 737178784Skmacy