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