crypto_libtomcrypt.c

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

Generated on Sat Nov 21 23:16:50 2009 for hostapd by  doxygen 1.6.1