1189251Ssam/* 2189251Ssam * WPA Supplicant / Crypto wrapper for LibTomCrypt (for internal TLSv1) 3189251Ssam * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> 4189251Ssam * 5189251Ssam * This program is free software; you can redistribute it and/or modify 6189251Ssam * it under the terms of the GNU General Public License version 2 as 7189251Ssam * published by the Free Software Foundation. 8189251Ssam * 9189251Ssam * Alternatively, this software may be distributed under the terms of BSD 10189251Ssam * license. 11189251Ssam * 12189251Ssam * See README and COPYING for more details. 13189251Ssam */ 14189251Ssam 15189251Ssam#include "includes.h" 16189251Ssam#include <tomcrypt.h> 17189251Ssam 18189251Ssam#include "common.h" 19189251Ssam#include "crypto.h" 20189251Ssam 21189251Ssam#ifndef mp_init_multi 22189251Ssam#define mp_init_multi ltc_init_multi 23189251Ssam#define mp_clear_multi ltc_deinit_multi 24189251Ssam#define mp_unsigned_bin_size(a) ltc_mp.unsigned_size(a) 25189251Ssam#define mp_to_unsigned_bin(a, b) ltc_mp.unsigned_write(a, b) 26189251Ssam#define mp_read_unsigned_bin(a, b, c) ltc_mp.unsigned_read(a, b, c) 27189251Ssam#define mp_exptmod(a,b,c,d) ltc_mp.exptmod(a,b,c,d) 28189251Ssam#endif 29189251Ssam 30189251Ssam 31214734Srpauloint md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 32189251Ssam{ 33189251Ssam hash_state md; 34189251Ssam size_t i; 35189251Ssam 36189251Ssam md4_init(&md); 37189251Ssam for (i = 0; i < num_elem; i++) 38189251Ssam md4_process(&md, addr[i], len[i]); 39189251Ssam md4_done(&md, mac); 40214734Srpaulo return 0; 41189251Ssam} 42189251Ssam 43189251Ssam 44189251Ssamvoid des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) 45189251Ssam{ 46189251Ssam u8 pkey[8], next, tmp; 47189251Ssam int i; 48189251Ssam symmetric_key skey; 49189251Ssam 50189251Ssam /* Add parity bits to the key */ 51189251Ssam next = 0; 52189251Ssam for (i = 0; i < 7; i++) { 53189251Ssam tmp = key[i]; 54189251Ssam pkey[i] = (tmp >> i) | next | 1; 55189251Ssam next = tmp << (7 - i); 56189251Ssam } 57189251Ssam pkey[i] = next | 1; 58189251Ssam 59189251Ssam des_setup(pkey, 8, 0, &skey); 60189251Ssam des_ecb_encrypt(clear, cypher, &skey); 61189251Ssam des_done(&skey); 62189251Ssam} 63189251Ssam 64189251Ssam 65214734Srpauloint md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 66189251Ssam{ 67189251Ssam hash_state md; 68189251Ssam size_t i; 69189251Ssam 70189251Ssam md5_init(&md); 71189251Ssam for (i = 0; i < num_elem; i++) 72189251Ssam md5_process(&md, addr[i], len[i]); 73189251Ssam md5_done(&md, mac); 74214734Srpaulo return 0; 75189251Ssam} 76189251Ssam 77189251Ssam 78214734Srpauloint sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) 79189251Ssam{ 80189251Ssam hash_state md; 81189251Ssam size_t i; 82189251Ssam 83189251Ssam sha1_init(&md); 84189251Ssam for (i = 0; i < num_elem; i++) 85189251Ssam sha1_process(&md, addr[i], len[i]); 86189251Ssam sha1_done(&md, mac); 87214734Srpaulo return 0; 88189251Ssam} 89189251Ssam 90189251Ssam 91189251Ssamvoid * aes_encrypt_init(const u8 *key, size_t len) 92189251Ssam{ 93189251Ssam symmetric_key *skey; 94189251Ssam skey = os_malloc(sizeof(*skey)); 95189251Ssam if (skey == NULL) 96189251Ssam return NULL; 97189251Ssam if (aes_setup(key, len, 0, skey) != CRYPT_OK) { 98189251Ssam os_free(skey); 99189251Ssam return NULL; 100189251Ssam } 101189251Ssam return skey; 102189251Ssam} 103189251Ssam 104189251Ssam 105189251Ssamvoid aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) 106189251Ssam{ 107189251Ssam symmetric_key *skey = ctx; 108189251Ssam aes_ecb_encrypt(plain, crypt, skey); 109189251Ssam} 110189251Ssam 111189251Ssam 112189251Ssamvoid aes_encrypt_deinit(void *ctx) 113189251Ssam{ 114189251Ssam symmetric_key *skey = ctx; 115189251Ssam aes_done(skey); 116189251Ssam os_free(skey); 117189251Ssam} 118189251Ssam 119189251Ssam 120189251Ssamvoid * aes_decrypt_init(const u8 *key, size_t len) 121189251Ssam{ 122189251Ssam symmetric_key *skey; 123189251Ssam skey = os_malloc(sizeof(*skey)); 124189251Ssam if (skey == NULL) 125189251Ssam return NULL; 126189251Ssam if (aes_setup(key, len, 0, skey) != CRYPT_OK) { 127189251Ssam os_free(skey); 128189251Ssam return NULL; 129189251Ssam } 130189251Ssam return skey; 131189251Ssam} 132189251Ssam 133189251Ssam 134189251Ssamvoid aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) 135189251Ssam{ 136189251Ssam symmetric_key *skey = ctx; 137189251Ssam aes_ecb_encrypt(plain, (u8 *) crypt, skey); 138189251Ssam} 139189251Ssam 140189251Ssam 141189251Ssamvoid aes_decrypt_deinit(void *ctx) 142189251Ssam{ 143189251Ssam symmetric_key *skey = ctx; 144189251Ssam aes_done(skey); 145189251Ssam os_free(skey); 146189251Ssam} 147189251Ssam 148189251Ssam 149189251Ssamstruct crypto_hash { 150189251Ssam enum crypto_hash_alg alg; 151189251Ssam int error; 152189251Ssam union { 153189251Ssam hash_state md; 154189251Ssam hmac_state hmac; 155189251Ssam } u; 156189251Ssam}; 157189251Ssam 158189251Ssam 159189251Ssamstruct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, 160189251Ssam size_t key_len) 161189251Ssam{ 162189251Ssam struct crypto_hash *ctx; 163189251Ssam 164189251Ssam ctx = os_zalloc(sizeof(*ctx)); 165189251Ssam if (ctx == NULL) 166189251Ssam return NULL; 167189251Ssam 168189251Ssam ctx->alg = alg; 169189251Ssam 170189251Ssam switch (alg) { 171189251Ssam case CRYPTO_HASH_ALG_MD5: 172189251Ssam if (md5_init(&ctx->u.md) != CRYPT_OK) 173189251Ssam goto fail; 174189251Ssam break; 175189251Ssam case CRYPTO_HASH_ALG_SHA1: 176189251Ssam if (sha1_init(&ctx->u.md) != CRYPT_OK) 177189251Ssam goto fail; 178189251Ssam break; 179189251Ssam case CRYPTO_HASH_ALG_HMAC_MD5: 180189251Ssam if (hmac_init(&ctx->u.hmac, find_hash("md5"), key, key_len) != 181189251Ssam CRYPT_OK) 182189251Ssam goto fail; 183189251Ssam break; 184189251Ssam case CRYPTO_HASH_ALG_HMAC_SHA1: 185189251Ssam if (hmac_init(&ctx->u.hmac, find_hash("sha1"), key, key_len) != 186189251Ssam CRYPT_OK) 187189251Ssam goto fail; 188189251Ssam break; 189189251Ssam default: 190189251Ssam goto fail; 191189251Ssam } 192189251Ssam 193189251Ssam return ctx; 194189251Ssam 195189251Ssamfail: 196189251Ssam os_free(ctx); 197189251Ssam return NULL; 198189251Ssam} 199189251Ssam 200189251Ssamvoid crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) 201189251Ssam{ 202189251Ssam if (ctx == NULL || ctx->error) 203189251Ssam return; 204189251Ssam 205189251Ssam switch (ctx->alg) { 206189251Ssam case CRYPTO_HASH_ALG_MD5: 207189251Ssam ctx->error = md5_process(&ctx->u.md, data, len) != CRYPT_OK; 208189251Ssam break; 209189251Ssam case CRYPTO_HASH_ALG_SHA1: 210189251Ssam ctx->error = sha1_process(&ctx->u.md, data, len) != CRYPT_OK; 211189251Ssam break; 212189251Ssam case CRYPTO_HASH_ALG_HMAC_MD5: 213189251Ssam case CRYPTO_HASH_ALG_HMAC_SHA1: 214189251Ssam ctx->error = hmac_process(&ctx->u.hmac, data, len) != CRYPT_OK; 215189251Ssam break; 216189251Ssam } 217189251Ssam} 218189251Ssam 219189251Ssam 220189251Ssamint crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) 221189251Ssam{ 222189251Ssam int ret = 0; 223189251Ssam unsigned long clen; 224189251Ssam 225189251Ssam if (ctx == NULL) 226189251Ssam return -2; 227189251Ssam 228189251Ssam if (mac == NULL || len == NULL) { 229189251Ssam os_free(ctx); 230189251Ssam return 0; 231189251Ssam } 232189251Ssam 233189251Ssam if (ctx->error) { 234189251Ssam os_free(ctx); 235189251Ssam return -2; 236189251Ssam } 237189251Ssam 238189251Ssam switch (ctx->alg) { 239189251Ssam case CRYPTO_HASH_ALG_MD5: 240189251Ssam if (*len < 16) { 241189251Ssam *len = 16; 242189251Ssam os_free(ctx); 243189251Ssam return -1; 244189251Ssam } 245189251Ssam *len = 16; 246189251Ssam if (md5_done(&ctx->u.md, mac) != CRYPT_OK) 247189251Ssam ret = -2; 248189251Ssam break; 249189251Ssam case CRYPTO_HASH_ALG_SHA1: 250189251Ssam if (*len < 20) { 251189251Ssam *len = 20; 252189251Ssam os_free(ctx); 253189251Ssam return -1; 254189251Ssam } 255189251Ssam *len = 20; 256189251Ssam if (sha1_done(&ctx->u.md, mac) != CRYPT_OK) 257189251Ssam ret = -2; 258189251Ssam break; 259189251Ssam case CRYPTO_HASH_ALG_HMAC_SHA1: 260189251Ssam if (*len < 20) { 261189251Ssam *len = 20; 262189251Ssam os_free(ctx); 263189251Ssam return -1; 264189251Ssam } 265189251Ssam /* continue */ 266189251Ssam case CRYPTO_HASH_ALG_HMAC_MD5: 267189251Ssam if (*len < 16) { 268189251Ssam *len = 16; 269189251Ssam os_free(ctx); 270189251Ssam return -1; 271189251Ssam } 272189251Ssam clen = *len; 273189251Ssam if (hmac_done(&ctx->u.hmac, mac, &clen) != CRYPT_OK) { 274189251Ssam os_free(ctx); 275189251Ssam return -1; 276189251Ssam } 277189251Ssam *len = clen; 278189251Ssam break; 279189251Ssam default: 280189251Ssam ret = -2; 281189251Ssam break; 282189251Ssam } 283189251Ssam 284189251Ssam os_free(ctx); 285189251Ssam 286189251Ssam return ret; 287189251Ssam} 288189251Ssam 289189251Ssam 290189251Ssamstruct crypto_cipher { 291189251Ssam int rc4; 292189251Ssam union { 293189251Ssam symmetric_CBC cbc; 294189251Ssam struct { 295189251Ssam size_t used_bytes; 296189251Ssam u8 key[16]; 297189251Ssam size_t keylen; 298189251Ssam } rc4; 299189251Ssam } u; 300189251Ssam}; 301189251Ssam 302189251Ssam 303189251Ssamstruct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, 304189251Ssam const u8 *iv, const u8 *key, 305189251Ssam size_t key_len) 306189251Ssam{ 307189251Ssam struct crypto_cipher *ctx; 308189251Ssam int idx, res, rc4 = 0; 309189251Ssam 310189251Ssam switch (alg) { 311189251Ssam case CRYPTO_CIPHER_ALG_AES: 312189251Ssam idx = find_cipher("aes"); 313189251Ssam break; 314189251Ssam case CRYPTO_CIPHER_ALG_3DES: 315189251Ssam idx = find_cipher("3des"); 316189251Ssam break; 317189251Ssam case CRYPTO_CIPHER_ALG_DES: 318189251Ssam idx = find_cipher("des"); 319189251Ssam break; 320189251Ssam case CRYPTO_CIPHER_ALG_RC2: 321189251Ssam idx = find_cipher("rc2"); 322189251Ssam break; 323189251Ssam case CRYPTO_CIPHER_ALG_RC4: 324189251Ssam idx = -1; 325189251Ssam rc4 = 1; 326189251Ssam break; 327189251Ssam default: 328189251Ssam return NULL; 329189251Ssam } 330189251Ssam 331189251Ssam ctx = os_zalloc(sizeof(*ctx)); 332189251Ssam if (ctx == NULL) 333189251Ssam return NULL; 334189251Ssam 335189251Ssam if (rc4) { 336189251Ssam ctx->rc4 = 1; 337189251Ssam if (key_len > sizeof(ctx->u.rc4.key)) { 338189251Ssam os_free(ctx); 339189251Ssam return NULL; 340189251Ssam } 341189251Ssam ctx->u.rc4.keylen = key_len; 342189251Ssam os_memcpy(ctx->u.rc4.key, key, key_len); 343189251Ssam } else { 344189251Ssam res = cbc_start(idx, iv, key, key_len, 0, &ctx->u.cbc); 345189251Ssam if (res != CRYPT_OK) { 346189251Ssam wpa_printf(MSG_DEBUG, "LibTomCrypt: Cipher start " 347189251Ssam "failed: %s", error_to_string(res)); 348189251Ssam os_free(ctx); 349189251Ssam return NULL; 350189251Ssam } 351189251Ssam } 352189251Ssam 353189251Ssam return ctx; 354189251Ssam} 355189251Ssam 356189251Ssamint crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, 357189251Ssam u8 *crypt, size_t len) 358189251Ssam{ 359189251Ssam int res; 360189251Ssam 361189251Ssam if (ctx->rc4) { 362189251Ssam if (plain != crypt) 363189251Ssam os_memcpy(crypt, plain, len); 364189251Ssam rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, 365189251Ssam ctx->u.rc4.used_bytes, crypt, len); 366189251Ssam ctx->u.rc4.used_bytes += len; 367189251Ssam return 0; 368189251Ssam } 369189251Ssam 370189251Ssam res = cbc_encrypt(plain, crypt, len, &ctx->u.cbc); 371189251Ssam if (res != CRYPT_OK) { 372189251Ssam wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC encryption " 373189251Ssam "failed: %s", error_to_string(res)); 374189251Ssam return -1; 375189251Ssam } 376189251Ssam return 0; 377189251Ssam} 378189251Ssam 379189251Ssam 380189251Ssamint crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, 381189251Ssam u8 *plain, size_t len) 382189251Ssam{ 383189251Ssam int res; 384189251Ssam 385189251Ssam if (ctx->rc4) { 386189251Ssam if (plain != crypt) 387189251Ssam os_memcpy(plain, crypt, len); 388189251Ssam rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, 389189251Ssam ctx->u.rc4.used_bytes, plain, len); 390189251Ssam ctx->u.rc4.used_bytes += len; 391189251Ssam return 0; 392189251Ssam } 393189251Ssam 394189251Ssam res = cbc_decrypt(crypt, plain, len, &ctx->u.cbc); 395189251Ssam if (res != CRYPT_OK) { 396189251Ssam wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC decryption " 397189251Ssam "failed: %s", error_to_string(res)); 398189251Ssam return -1; 399189251Ssam } 400189251Ssam 401189251Ssam return 0; 402189251Ssam} 403189251Ssam 404189251Ssam 405189251Ssamvoid crypto_cipher_deinit(struct crypto_cipher *ctx) 406189251Ssam{ 407189251Ssam if (!ctx->rc4) 408189251Ssam cbc_done(&ctx->u.cbc); 409189251Ssam os_free(ctx); 410189251Ssam} 411189251Ssam 412189251Ssam 413189251Ssamstruct crypto_public_key { 414189251Ssam rsa_key rsa; 415189251Ssam}; 416189251Ssam 417189251Ssamstruct crypto_private_key { 418189251Ssam rsa_key rsa; 419189251Ssam}; 420189251Ssam 421189251Ssam 422189251Ssamstruct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len) 423189251Ssam{ 424189251Ssam int res; 425189251Ssam struct crypto_public_key *pk; 426189251Ssam 427189251Ssam pk = os_zalloc(sizeof(*pk)); 428189251Ssam if (pk == NULL) 429189251Ssam return NULL; 430189251Ssam 431189251Ssam res = rsa_import(key, len, &pk->rsa); 432189251Ssam if (res != CRYPT_OK) { 433189251Ssam wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import " 434189251Ssam "public key (res=%d '%s')", 435189251Ssam res, error_to_string(res)); 436189251Ssam os_free(pk); 437189251Ssam return NULL; 438189251Ssam } 439189251Ssam 440189251Ssam if (pk->rsa.type != PK_PUBLIC) { 441189251Ssam wpa_printf(MSG_ERROR, "LibTomCrypt: Public key was not of " 442189251Ssam "correct type"); 443189251Ssam rsa_free(&pk->rsa); 444189251Ssam os_free(pk); 445189251Ssam return NULL; 446189251Ssam } 447189251Ssam 448189251Ssam return pk; 449189251Ssam} 450189251Ssam 451189251Ssam 452189251Ssamstruct crypto_private_key * crypto_private_key_import(const u8 *key, 453214734Srpaulo size_t len, 454214734Srpaulo const char *passwd) 455189251Ssam{ 456189251Ssam int res; 457189251Ssam struct crypto_private_key *pk; 458189251Ssam 459189251Ssam pk = os_zalloc(sizeof(*pk)); 460189251Ssam if (pk == NULL) 461189251Ssam return NULL; 462189251Ssam 463189251Ssam res = rsa_import(key, len, &pk->rsa); 464189251Ssam if (res != CRYPT_OK) { 465189251Ssam wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import " 466189251Ssam "private key (res=%d '%s')", 467189251Ssam res, error_to_string(res)); 468189251Ssam os_free(pk); 469189251Ssam return NULL; 470189251Ssam } 471189251Ssam 472189251Ssam if (pk->rsa.type != PK_PRIVATE) { 473189251Ssam wpa_printf(MSG_ERROR, "LibTomCrypt: Private key was not of " 474189251Ssam "correct type"); 475189251Ssam rsa_free(&pk->rsa); 476189251Ssam os_free(pk); 477189251Ssam return NULL; 478189251Ssam } 479189251Ssam 480189251Ssam return pk; 481189251Ssam} 482189251Ssam 483189251Ssam 484189251Ssamstruct crypto_public_key * crypto_public_key_from_cert(const u8 *buf, 485189251Ssam size_t len) 486189251Ssam{ 487189251Ssam /* No X.509 support in LibTomCrypt */ 488189251Ssam return NULL; 489189251Ssam} 490189251Ssam 491189251Ssam 492189251Ssamstatic int pkcs1_generate_encryption_block(u8 block_type, size_t modlen, 493189251Ssam const u8 *in, size_t inlen, 494189251Ssam u8 *out, size_t *outlen) 495189251Ssam{ 496189251Ssam size_t ps_len; 497189251Ssam u8 *pos; 498189251Ssam 499189251Ssam /* 500189251Ssam * PKCS #1 v1.5, 8.1: 501189251Ssam * 502189251Ssam * EB = 00 || BT || PS || 00 || D 503189251Ssam * BT = 00 or 01 for private-key operation; 02 for public-key operation 504189251Ssam * PS = k-3-||D||; at least eight octets 505189251Ssam * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero) 506189251Ssam * k = length of modulus in octets (modlen) 507189251Ssam */ 508189251Ssam 509189251Ssam if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) { 510189251Ssam wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer " 511189251Ssam "lengths (modlen=%lu outlen=%lu inlen=%lu)", 512189251Ssam __func__, (unsigned long) modlen, 513189251Ssam (unsigned long) *outlen, 514189251Ssam (unsigned long) inlen); 515189251Ssam return -1; 516189251Ssam } 517189251Ssam 518189251Ssam pos = out; 519189251Ssam *pos++ = 0x00; 520189251Ssam *pos++ = block_type; /* BT */ 521189251Ssam ps_len = modlen - inlen - 3; 522189251Ssam switch (block_type) { 523189251Ssam case 0: 524189251Ssam os_memset(pos, 0x00, ps_len); 525189251Ssam pos += ps_len; 526189251Ssam break; 527189251Ssam case 1: 528189251Ssam os_memset(pos, 0xff, ps_len); 529189251Ssam pos += ps_len; 530189251Ssam break; 531189251Ssam case 2: 532189251Ssam if (os_get_random(pos, ps_len) < 0) { 533189251Ssam wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get " 534189251Ssam "random data for PS", __func__); 535189251Ssam return -1; 536189251Ssam } 537189251Ssam while (ps_len--) { 538189251Ssam if (*pos == 0x00) 539189251Ssam *pos = 0x01; 540189251Ssam pos++; 541189251Ssam } 542189251Ssam break; 543189251Ssam default: 544189251Ssam wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type " 545189251Ssam "%d", __func__, block_type); 546189251Ssam return -1; 547189251Ssam } 548189251Ssam *pos++ = 0x00; 549189251Ssam os_memcpy(pos, in, inlen); /* D */ 550189251Ssam 551189251Ssam return 0; 552189251Ssam} 553189251Ssam 554189251Ssam 555189251Ssamstatic int crypto_rsa_encrypt_pkcs1(int block_type, rsa_key *key, int key_type, 556189251Ssam const u8 *in, size_t inlen, 557189251Ssam u8 *out, size_t *outlen) 558189251Ssam{ 559189251Ssam unsigned long len, modlen; 560189251Ssam int res; 561189251Ssam 562189251Ssam modlen = mp_unsigned_bin_size(key->N); 563189251Ssam 564189251Ssam if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen, 565189251Ssam out, outlen) < 0) 566189251Ssam return -1; 567189251Ssam 568189251Ssam len = *outlen; 569189251Ssam res = rsa_exptmod(out, modlen, out, &len, key_type, key); 570189251Ssam if (res != CRYPT_OK) { 571189251Ssam wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s", 572189251Ssam error_to_string(res)); 573189251Ssam return -1; 574189251Ssam } 575189251Ssam *outlen = len; 576189251Ssam 577189251Ssam return 0; 578189251Ssam} 579189251Ssam 580189251Ssam 581189251Ssamint crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key, 582189251Ssam const u8 *in, size_t inlen, 583189251Ssam u8 *out, size_t *outlen) 584189251Ssam{ 585189251Ssam return crypto_rsa_encrypt_pkcs1(2, &key->rsa, PK_PUBLIC, in, inlen, 586189251Ssam out, outlen); 587189251Ssam} 588189251Ssam 589189251Ssam 590189251Ssamint crypto_private_key_sign_pkcs1(struct crypto_private_key *key, 591189251Ssam const u8 *in, size_t inlen, 592189251Ssam u8 *out, size_t *outlen) 593189251Ssam{ 594189251Ssam return crypto_rsa_encrypt_pkcs1(1, &key->rsa, PK_PRIVATE, in, inlen, 595189251Ssam out, outlen); 596189251Ssam} 597189251Ssam 598189251Ssam 599189251Ssamvoid crypto_public_key_free(struct crypto_public_key *key) 600189251Ssam{ 601189251Ssam if (key) { 602189251Ssam rsa_free(&key->rsa); 603189251Ssam os_free(key); 604189251Ssam } 605189251Ssam} 606189251Ssam 607189251Ssam 608189251Ssamvoid crypto_private_key_free(struct crypto_private_key *key) 609189251Ssam{ 610189251Ssam if (key) { 611189251Ssam rsa_free(&key->rsa); 612189251Ssam os_free(key); 613189251Ssam } 614189251Ssam} 615189251Ssam 616189251Ssam 617189251Ssamint crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key, 618189251Ssam const u8 *crypt, size_t crypt_len, 619189251Ssam u8 *plain, size_t *plain_len) 620189251Ssam{ 621189251Ssam int res; 622189251Ssam unsigned long len; 623189251Ssam u8 *pos; 624189251Ssam 625189251Ssam len = *plain_len; 626189251Ssam res = rsa_exptmod(crypt, crypt_len, plain, &len, PK_PUBLIC, 627189251Ssam &key->rsa); 628189251Ssam if (res != CRYPT_OK) { 629189251Ssam wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s", 630189251Ssam error_to_string(res)); 631189251Ssam return -1; 632189251Ssam } 633189251Ssam 634189251Ssam /* 635189251Ssam * PKCS #1 v1.5, 8.1: 636189251Ssam * 637189251Ssam * EB = 00 || BT || PS || 00 || D 638189251Ssam * BT = 01 639189251Ssam * PS = k-3-||D|| times FF 640189251Ssam * k = length of modulus in octets 641189251Ssam */ 642189251Ssam 643189251Ssam if (len < 3 + 8 + 16 /* min hash len */ || 644189251Ssam plain[0] != 0x00 || plain[1] != 0x01 || plain[2] != 0xff) { 645189251Ssam wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " 646189251Ssam "structure"); 647189251Ssam return -1; 648189251Ssam } 649189251Ssam 650189251Ssam pos = plain + 3; 651189251Ssam while (pos < plain + len && *pos == 0xff) 652189251Ssam pos++; 653189251Ssam if (pos - plain - 2 < 8) { 654189251Ssam /* PKCS #1 v1.5, 8.1: At least eight octets long PS */ 655189251Ssam wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature " 656189251Ssam "padding"); 657189251Ssam return -1; 658189251Ssam } 659189251Ssam 660189251Ssam if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) { 661189251Ssam wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " 662189251Ssam "structure (2)"); 663189251Ssam return -1; 664189251Ssam } 665189251Ssam pos++; 666189251Ssam len -= pos - plain; 667189251Ssam 668189251Ssam /* Strip PKCS #1 header */ 669189251Ssam os_memmove(plain, pos, len); 670189251Ssam *plain_len = len; 671189251Ssam 672189251Ssam return 0; 673189251Ssam} 674189251Ssam 675189251Ssam 676189251Ssamint crypto_global_init(void) 677189251Ssam{ 678189251Ssam ltc_mp = tfm_desc; 679189251Ssam /* TODO: only register algorithms that are really needed */ 680189251Ssam if (register_hash(&md4_desc) < 0 || 681189251Ssam register_hash(&md5_desc) < 0 || 682189251Ssam register_hash(&sha1_desc) < 0 || 683189251Ssam register_cipher(&aes_desc) < 0 || 684189251Ssam register_cipher(&des_desc) < 0 || 685189251Ssam register_cipher(&des3_desc) < 0) { 686189251Ssam wpa_printf(MSG_ERROR, "TLSv1: Failed to register " 687189251Ssam "hash/cipher functions"); 688189251Ssam return -1; 689189251Ssam } 690189251Ssam 691189251Ssam return 0; 692189251Ssam} 693189251Ssam 694189251Ssam 695189251Ssamvoid crypto_global_deinit(void) 696189251Ssam{ 697189251Ssam} 698189251Ssam 699189251Ssam 700214734Srpaulo#ifdef CONFIG_MODEXP 701189251Ssam 702189251Ssamint crypto_mod_exp(const u8 *base, size_t base_len, 703189251Ssam const u8 *power, size_t power_len, 704189251Ssam const u8 *modulus, size_t modulus_len, 705189251Ssam u8 *result, size_t *result_len) 706189251Ssam{ 707189251Ssam void *b, *p, *m, *r; 708189251Ssam 709189251Ssam if (mp_init_multi(&b, &p, &m, &r, NULL) != CRYPT_OK) 710189251Ssam return -1; 711189251Ssam 712189251Ssam if (mp_read_unsigned_bin(b, (u8 *) base, base_len) != CRYPT_OK || 713189251Ssam mp_read_unsigned_bin(p, (u8 *) power, power_len) != CRYPT_OK || 714189251Ssam mp_read_unsigned_bin(m, (u8 *) modulus, modulus_len) != CRYPT_OK) 715189251Ssam goto fail; 716189251Ssam 717189251Ssam if (mp_exptmod(b, p, m, r) != CRYPT_OK) 718189251Ssam goto fail; 719189251Ssam 720189251Ssam *result_len = mp_unsigned_bin_size(r); 721189251Ssam if (mp_to_unsigned_bin(r, result) != CRYPT_OK) 722189251Ssam goto fail; 723189251Ssam 724189251Ssam mp_clear_multi(b, p, m, r, NULL); 725189251Ssam return 0; 726189251Ssam 727189251Ssamfail: 728189251Ssam mp_clear_multi(b, p, m, r, NULL); 729189251Ssam return -1; 730189251Ssam} 731189251Ssam 732214734Srpaulo#endif /* CONFIG_MODEXP */ 733