| /////////////////////////////////////////////////////////////////////////////// |
| // |
| // Copyright (c) 2000-2018 Ericsson Telecom AB |
| // |
| // All rights reserved. This program and the accompanying materials |
| // are made available under the terms of the Eclipse Public License v2.0 |
| // which accompanies this distribution, and is available at |
| // https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html |
| ///////////////////////////////////////////////////////////////////////////////
|
| //
|
| // File: EAP_EncDec.cc
|
| // Rev: R6A |
| // Prodnr: CNL 113 722
|
| // Updated: 2014-01-24
|
| // Contact: http://ttcn.ericsson.se
|
| // Reference: RFC 3748(Extensible Authentication Protocol)
|
| // RFC 4187(EAP-AKA)
|
| // RFC 5448(EAP-AKA')
|
| // RFC 4186(EAP-SIM)
|
| // RFC 5281(EAP-TTLS)
|
| ///////////////////////////////////////////////////////////////////////////////
|
|
|
| #include "EAP_Types.hh"
|
| #include <stdint.h>
|
| #include <openssl/sha.h>
|
| #include <openssl/bn.h>
|
|
|
| #include <openssl/asn1.h>
|
| #include <openssl/x509.h>
|
|
|
|
|
| namespace EAP__Types {
|
|
|
| OCTETSTRING enc__PDU__EAP(const PDU__EAP& pdu)
|
| {
|
| if(TTCN_Logger::log_this_event(TTCN_DEBUG)) {
|
| TTCN_Logger::begin_event(TTCN_DEBUG);
|
| TTCN_Logger::log_event("Encoding PDU_EAP: ");
|
| pdu.log();
|
| TTCN_Logger::end_event();
|
| }
|
|
|
| TTCN_EncDec::error_type_t err;
|
| TTCN_Buffer buf;
|
| buf.clear();
|
| TTCN_EncDec::clear_error();
|
| TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING);
|
| pdu.encode(PDU__EAP_descr_, buf, TTCN_EncDec::CT_RAW);
|
| err = TTCN_EncDec::get_last_error_type();
|
| if(err != TTCN_EncDec::ET_NONE)
|
| TTCN_warning("Encoding error: %s\n", TTCN_EncDec::get_error_str());
|
|
|
| OCTETSTRING ret_val(buf.get_len(), buf.get_data());
|
| if(TTCN_Logger::log_this_event(TTCN_DEBUG)) {
|
| TTCN_Logger::begin_event(TTCN_DEBUG);
|
| TTCN_Logger::log_event("PDU_EAP after encoding: ");
|
| ret_val.log();
|
| TTCN_Logger::end_event();
|
| }
|
|
|
| return ret_val;
|
| }
|
|
|
| PDU__EAP dec__PDU__EAP(const OCTETSTRING& stream)
|
| {
|
| if(TTCN_Logger::log_this_event(TTCN_DEBUG)) {
|
| TTCN_Logger::begin_event(TTCN_DEBUG);
|
| TTCN_Logger::log_event("Decoding PDU_EAP: ");
|
| stream.log();
|
| TTCN_Logger::end_event();
|
| }
|
|
|
| TTCN_EncDec::error_type_t err;
|
| TTCN_EncDec::clear_error();
|
| TTCN_Buffer buf;
|
| buf.put_os(stream);
|
| PDU__EAP ret_val;
|
| TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING);
|
| ret_val.decode(PDU__EAP_descr_, buf, TTCN_EncDec::CT_RAW);
|
| err = TTCN_EncDec::get_last_error_type();
|
| if(err != TTCN_EncDec::ET_NONE)
|
| TTCN_warning("Decoding error: %s\n", TTCN_EncDec::get_error_str());
|
|
|
| if(TTCN_Logger::log_this_event(TTCN_DEBUG)) {
|
| TTCN_Logger::begin_event(TTCN_DEBUG);
|
| TTCN_Logger::log_event("Decoded PDU_EAP: ");
|
| ret_val.log();
|
| TTCN_Logger::end_event();
|
| }
|
|
|
| return ret_val;
|
| }
|
|
|
| OCTETSTRING enc__AKA__Attrib(const EAP__AKA__Attrib__List& pdu)
|
| {
|
| if(TTCN_Logger::log_this_event(TTCN_DEBUG)) {
|
| TTCN_Logger::begin_event(TTCN_DEBUG);
|
| TTCN_Logger::log_event("Encoding EAP_AKA_Attrib_List: ");
|
| pdu.log();
|
| TTCN_Logger::end_event();
|
| }
|
|
|
| TTCN_EncDec::error_type_t err;
|
| TTCN_Buffer buf;
|
| buf.clear();
|
| TTCN_EncDec::clear_error();
|
| TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING);
|
| pdu.encode(EAP__AKA__Attrib__List_descr_, buf, TTCN_EncDec::CT_RAW);
|
| err = TTCN_EncDec::get_last_error_type();
|
| if(err != TTCN_EncDec::ET_NONE)
|
| TTCN_warning("Encoding error: %s\n", TTCN_EncDec::get_error_str());
|
|
|
| OCTETSTRING ret_val(buf.get_len(), buf.get_data());
|
| if(TTCN_Logger::log_this_event(TTCN_DEBUG)) {
|
| TTCN_Logger::begin_event(TTCN_DEBUG);
|
| TTCN_Logger::log_event("EAP_AKA_Attrib_List after encoding: ");
|
| ret_val.log();
|
| TTCN_Logger::end_event();
|
| }
|
|
|
| return ret_val;
|
| }
|
|
|
| EAP__AKA__Attrib__List dec__AKA__Attrib(const OCTETSTRING& stream)
|
| {
|
| if(TTCN_Logger::log_this_event(TTCN_DEBUG)) {
|
| TTCN_Logger::begin_event(TTCN_DEBUG);
|
| TTCN_Logger::log_event("Decoding EAP_AKA_Attrib_List: ");
|
| stream.log();
|
| TTCN_Logger::end_event();
|
| }
|
|
|
| TTCN_EncDec::error_type_t err;
|
| TTCN_EncDec::clear_error();
|
| TTCN_Buffer buf;
|
| buf.put_os(stream);
|
| EAP__AKA__Attrib__List ret_val;
|
| TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING);
|
| ret_val.decode(EAP__AKA__Attrib__List_descr_, buf, TTCN_EncDec::CT_RAW);
|
| err = TTCN_EncDec::get_last_error_type();
|
| if(err != TTCN_EncDec::ET_NONE)
|
| TTCN_warning("Decoding error: %s\n", TTCN_EncDec::get_error_str());
|
|
|
| if(TTCN_Logger::log_this_event(TTCN_DEBUG)) {
|
| TTCN_Logger::begin_event(TTCN_DEBUG);
|
| TTCN_Logger::log_event("Decoded EAP_AKA_Attrib_List: ");
|
| ret_val.log();
|
| TTCN_Logger::end_event();
|
| }
|
|
|
| return ret_val;
|
| }
|
|
|
|
|
| typedef unsigned char u8;
|
| |
|
|
| void sha1_vector(size_t num_elem, const unsigned char *addr[], const size_t *len, unsigned char *mac)
|
| {
|
| SHA_CTX ctx;
|
| SHA_Init(&ctx);
|
|
|
| size_t i;
|
|
|
| for (i = 0; i < num_elem; i++) {
|
|
|
| SHA1_Update(&ctx, addr[i], len[i]);
|
| }
|
|
|
| SHA1_Final(mac, &ctx);
|
| }
|
| |
|
|
| OCTETSTRING eap__sim__derive__mk(const OCTETSTRING& identity,
|
| const OCTETSTRING& nonce_mt, const INTEGER& selected_version,
|
| const OCTETSTRING& ver_list,
|
| const OCTETSTRING& kc)
|
| {
|
| unsigned char mk[20];
|
|
|
| unsigned char sel_ver[2];
|
| const unsigned char *addr[5];
|
| size_t len[5];
|
|
|
| addr[0] = (const unsigned char*)identity;
|
|
|
| len[0] = identity.lengthof();
|
|
|
| addr[1] = (const unsigned char*)kc;
|
|
|
| len[1] = kc.lengthof();
|
|
|
| addr[2] = (const unsigned char*)nonce_mt;
|
|
|
| len[2] = nonce_mt.lengthof();
|
|
|
| addr[3] = (const unsigned char*)ver_list;
|
|
|
| len[3] = ver_list.lengthof();
|
|
|
| addr[4] = sel_ver;
|
|
|
| len[4] = 2;
|
|
|
| sel_ver[0] = ((unsigned short) (selected_version)) >> 8;
|
| sel_ver[1] = ((unsigned short) (selected_version)) & 0xff;
|
|
|
|
|
| /* MK = SHA1(Identity|n*Kc|NONCE_MT|Version List|Selected Version) */
|
| sha1_vector(5, addr, len, mk);
|
|
|
| OCTETSTRING mk_value(20,mk);
|
| return mk_value;
|
| }
|
|
|
| #define bswap_32(a) ((((unsigned int) (a) << 24) & 0xff000000) | \ |
| (((unsigned int) (a) << 8) & 0xff0000) | \ |
| (((unsigned int) (a) >> 8) & 0xff00) | \ |
| (((unsigned int) (a) >> 24) & 0xff)) |
| |
| #ifdef __linux__ |
| #define host_to_be32(n) ((unsigned int) bswap_32((n))) |
| #else |
| #define host_to_be32(n) (n) |
| #endif
|
|
|
|
|
|
|
| OCTETSTRING fips186__2__prf(const OCTETSTRING& input /**const unsigned char *seed, size_t seed_len, unsigned char *x, size_t xlen*/)
|
| {
|
| const unsigned char* seed=(const unsigned char*)input;
|
| size_t seed_len=input.lengthof();
|
| size_t xlen=160;
|
| unsigned char x[xlen];
|
|
|
| unsigned char xkey[64];
|
| unsigned int _t[5];
|
| int i, j, m, k;
|
| unsigned char *xpos = x;
|
|
|
| unsigned int carry;
|
|
|
| if (seed_len > sizeof(xkey))
|
| seed_len = sizeof(xkey);
|
|
|
|
|
| /* FIPS 186-2 + change notice 1 */
|
|
|
| memcpy(xkey, seed, seed_len);
|
|
|
| memset(xkey + seed_len, 0, 64 - seed_len);
|
|
|
| SHA_CTX ctx;
|
|
|
| m = xlen / 40;
|
|
|
| for (j = 0; j < m; j++) {
|
| /* XSEED_j = 0 */
|
| for (i = 0; i < 2; i++) {
|
| /* XVAL = (XKEY + XSEED_j) mod 2^b */
|
|
|
| /* w_i = G(t, XVAL) */
|
|
|
| SHA_Init(&ctx);
|
|
|
| SHA1_Transform(&ctx , xkey);
|
|
|
| _t[0] = host_to_be32(ctx.h0);
|
| _t[1] = host_to_be32(ctx.h1);
|
| _t[2] = host_to_be32(ctx.h2);
|
| _t[3] = host_to_be32(ctx.h3);
|
| _t[4] = host_to_be32(ctx.h4);
|
|
|
| memcpy(xpos, _t, 20);
|
|
|
|
|
| /* XKEY = (1 + XKEY + w_i) mod 2^b */
|
| carry = 1;
|
|
|
| for (k = 19; k >= 0; k--) {
|
| carry += xkey[k] + xpos[k];
|
|
|
| xkey[k] = carry & 0xff;
|
|
|
| carry >>= 8;
|
| }
|
|
|
| xpos += 20;
|
|
|
| }
|
| /* x_j = w_0|w_1 */
|
| }
|
|
|
| OCTETSTRING output(xlen,x);
|
| return output;
|
| }
|
|
|
|
|
|
|
| OCTETSTRING eap__aka__derive__mk(const OCTETSTRING& p_identity, const OCTETSTRING& p_ik, const OCTETSTRING& p_ck)
|
| {
|
| unsigned char mk[20];
|
|
|
| const u8 *identity=(const u8 *)p_identity;
|
| size_t identity_len=p_identity.lengthof();
|
| const u8 *ik=(const u8 *)p_ik;
|
| const u8 *ck=(const u8 *)p_ck;
|
|
|
|
|
|
|
| const u8 *addr[3];
|
|
|
| size_t len[3];
|
|
|
| addr[0] = identity;
|
|
|
| len[0] = identity_len;
|
|
|
| addr[1] = ik;
|
|
|
| len[1] = 16;
|
|
|
| addr[2] = ck;
|
|
|
| len[2] = 16;
|
|
|
| /* MK = SHA1(Identity|IK|CK) */
|
| sha1_vector(3, addr, len, mk);
|
|
|
| OCTETSTRING mk_value(20,mk);
|
| return mk_value;
|
| } |
| |
| OCTETSTRING eap__aka__derive__reauth__msk__emsk(const OCTETSTRING& p_identity, const OCTETSTRING& p_counter, const OCTETSTRING& p_nonce_s, const OCTETSTRING& p_mk) |
| { |
| unsigned char reauth_msk_emsk[20]; |
| OCTETSTRING source_os = p_identity + p_counter + p_nonce_s + p_mk; |
| const unsigned char *source = (const unsigned char*)source_os; |
| |
| /* MK = SHA1(Identity|counter|NONCE_S|MK) */ |
| SHA1(source, source_os.lengthof(), reauth_msk_emsk); |
| |
| OCTETSTRING emsk_value(20,reauth_msk_emsk); |
| return emsk_value; |
| }
|
|
|
| //Added for EPC
|
|
|
|
|
| #define EAP_AKA_IK_LEN 16
|
| #define EAP_AKA_CK_LEN 16
|
| #define EAP_SIM_K_ENCR_LEN 16
|
| #define EAP_AKA_PRIME_K_AUT_LEN 32
|
| #define EAP_AKA_PRIME_K_RE_LEN 32
|
| #define EAP_MSK_LEN 64
|
| #define EAP_EMSK_LEN 64
|
| #define SHA256_MAC_LEN 32
|
| #define SHA256_CHECKCODE_LEN 32
|
|
|
|
|
|
|
|
|
| /**
|
| * sha256_vector - SHA256 hash for data vector
|
| * @num_elem: Number of elements in the data vector
|
| * @addr: Pointers to the data areas
|
| * @len: Lengths of the data blocks
|
| * @mac: Buffer for the hash
|
| * Returns: 0 on success, -1 of failure
|
| */
|
| int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
|
| u8 *mac)
|
| {
|
|
|
| SHA256_CTX ctx;
|
| size_t i;
|
|
|
| SHA256_Init(&ctx);
|
| for (i = 0; i < num_elem; i++) {
|
| SHA256_Update(&ctx, addr[i], len[i]);
|
| }
|
| if (SHA256_Final(mac, &ctx))
|
| return -1;
|
| return 0;
|
|
|
| }
|
|
|
| /**
|
| * hmac_sha256_vector - HMAC-SHA256 over data vector (RFC 2104)
|
| * @key: Key for HMAC operations
|
| * @key_len: Length of the key in bytes
|
| * @num_elem: Number of elements in the data vector
|
| * @addr: Pointers to the data areas
|
| * @len: Lengths of the data blocks
|
| * @mac: Buffer for the hash (32 bytes)
|
| */
|
| void hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
|
| const u8 *addr[], const size_t *len, u8 *mac)
|
| {
|
| unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */
|
| unsigned char tk[32];
|
| const u8 *_addr[6];
|
| size_t _len[6], i;
|
|
|
| if (num_elem > 5) {
|
| /*
|
| * Fixed limit on the number of fragments to avoid having to
|
| * allocate memory (which could fail).
|
| */
|
| return;
|
| }
|
|
|
| /* if key is longer than 64 bytes reset it to key = SHA256(key) */
|
| if (key_len > 64) {
|
| sha256_vector(1, &key, &key_len, tk);
|
| key = tk;
|
| key_len = 32;
|
| }
|
|
|
| /* the HMAC_SHA256 transform looks like:
|
| *
|
| * SHA256(K XOR opad, SHA256(K XOR ipad, text))
|
| *
|
| * where K is an n byte key
|
| * ipad is the byte 0x36 repeated 64 times
|
| * opad is the byte 0x5c repeated 64 times
|
| * and text is the data being protected */
|
|
|
| /* start out by storing key in ipad */
|
| memset(k_pad, 0, sizeof(k_pad));
|
| memcpy(k_pad, key, key_len);
|
| /* XOR key with ipad values */
|
| for (i = 0; i < 64; i++)
|
| k_pad[i] ^= 0x36;
|
|
|
| /* perform inner SHA256 */
|
| _addr[0] = k_pad;
|
| _len[0] = 64;
|
| for (i = 0; i < num_elem; i++) {
|
| _addr[i + 1] = addr[i];
|
| _len[i + 1] = len[i];
|
| }
|
| sha256_vector(1 + num_elem, _addr, _len, mac);
|
|
|
| memset(k_pad, 0, sizeof(k_pad));
|
| memcpy(k_pad, key, key_len);
|
| /* XOR key with opad values */
|
| for (i = 0; i < 64; i++)
|
| k_pad[i] ^= 0x5c;
|
|
|
| /* perform outer SHA256 */
|
| _addr[0] = k_pad;
|
| _len[0] = 64;
|
| _addr[1] = mac;
|
| _len[1] = SHA256_MAC_LEN;
|
| sha256_vector(2, _addr, _len, mac);
|
| }
|
| |
|
|
| static void prf_prime(const u8 *k, const char *seed1,
|
| const u8 *seed2, size_t seed2_len,
|
| const u8 *seed3, size_t seed3_len,
|
| u8 *res, size_t res_len)
|
| {
|
| const u8 *addr[5];
|
| size_t len[5];
|
| u8 hash[SHA256_MAC_LEN];
|
| u8 iter;
|
| /*
|
| * PRF'(K,S) = T1 | T2 | T3 | T4 | ...
|
| * T1 = HMAC-SHA-256 (K, S | 0x01)
|
| * T2 = HMAC-SHA-256 (K, T1 | S | 0x02)
|
| * T3 = HMAC-SHA-256 (K, T2 | S | 0x03)
|
| * T4 = HMAC-SHA-256 (K, T3 | S | 0x04)
|
| * ...
|
| */
|
|
|
| addr[0] = hash;
|
| len[0] = 0;
|
| addr[1] = (const u8 *) seed1;
|
| len[1] = strlen(seed1);
|
| addr[2] = seed2;
|
| len[2] = seed2_len;
|
| addr[3] = seed3;
|
| len[3] = seed3_len;
|
| addr[4] = &iter;
|
| len[4] = 1;
|
|
|
| iter = 0;
|
| while (res_len) {
|
| size_t hlen;
|
| iter++;
|
| hmac_sha256_vector(k, 32, 5, addr, len, hash);
|
| len[0] = SHA256_MAC_LEN;
|
| hlen = res_len > SHA256_MAC_LEN ? SHA256_MAC_LEN : res_len;
|
| memcpy(res, hash, hlen);
|
| res += hlen;
|
| res_len -= hlen;
|
| }
|
|
|
| }
|
|
|
| OCTETSTRING eap__akaprime__derive__mk(const OCTETSTRING& p_identity, const OCTETSTRING& p_ik, const OCTETSTRING& p_ck)
|
| {
|
| OCTETSTRING mk;
|
|
|
| //const char *identity=oct2str(p_identity).c_str();
|
| //const char *identity=(const char *)oct2str(p_identity);
|
| //char *identity=oct2str(p_identity);
|
|
|
| //size_t identity_len=p_identity.lengthof();
|
|
|
| const u8 *identity=(const u8 *)p_identity;
|
| size_t identity_len=p_identity.lengthof();
|
| const u8 *ik=(const u8 *)p_ik;
|
| const u8 *ck=(const u8 *)p_ck;
|
|
|
| //char *ik=oct2str(p_ik);
|
| //char *ck=oct2str(p_ck);
|
| //const unsigned char *ik=(const unsigned char *)p_ik;
|
|
|
| //const unsigned char *ck=(const unsigned char *)p_ck;
|
|
|
| uint8_t key[EAP_AKA_IK_LEN + EAP_AKA_CK_LEN];
|
| uint8_t keys[EAP_SIM_K_ENCR_LEN + EAP_AKA_PRIME_K_AUT_LEN +
|
| EAP_AKA_PRIME_K_RE_LEN + EAP_MSK_LEN + EAP_EMSK_LEN];
|
| // uint8_t *pos;
|
|
|
| memset(key, 0, sizeof(key));
|
| memset(keys, 0, sizeof(keys));
|
| memcpy(key, ik, EAP_AKA_IK_LEN);
|
| memcpy(key + EAP_AKA_IK_LEN, ck, EAP_AKA_CK_LEN);
|
|
|
| prf_prime(key, "EAP-AKA'", (const uint8_t*)identity, identity_len, NULL, 0,
|
| keys, sizeof(keys));
|
| OCTETSTRING mk_value(208,keys);
|
| return mk_value;
|
| }
|
|
|
| OCTETSTRING Calculate__AT__CheckCode(const OCTETSTRING& rcv_eappayload_octstring,const OCTETSTRING& send_eappayload_octstring)
|
| {
|
| const u8 *addr;
|
| size_t len;
|
| u8 hash[SHA256_CHECKCODE_LEN];
|
|
|
| OCTETSTRING eappayload1=rcv_eappayload_octstring+send_eappayload_octstring;
|
|
|
| const u8* eappayload=(const u8 *)eappayload1;
|
|
|
| addr=eappayload;
|
|
|
| len=eappayload1.lengthof();;
|
|
|
| sha256_vector(1, &addr, &len, hash);
|
|
|
| OCTETSTRING output(32,hash);
|
|
|
| return output;
|
|
|
| }
|
| |
|
|
| const unsigned char * change_ByteOrder(unsigned int in)
|
| {
|
| static unsigned char out[4] ;
|
| out[0] = (unsigned char)((in & 0xFF000000) >> 24);
|
| out[1] = (unsigned char)((in & 0x00FF0000) >> 16);
|
| out[2] = (unsigned char)((in & 0x0000FF00) >> 8);
|
| out[3] = (unsigned char)(in & 0x000000FF);
|
| return out;
|
| } // change_ByteOrder
|
| |
|
|
| OCTETSTRING f__calc__Kaut(const OCTETSTRING& input, OCTETSTRING& Kencr)
|
| {
|
| unsigned char xval[64];
|
| unsigned char xkey[SHA_DIGEST_LENGTH];
|
| SHA1((const unsigned char*)input, input.lengthof(), xkey);
|
| unsigned char dummy[128];
|
| unsigned char x_out[80];//40 bytes for each (m) iteration
|
| int m = 2;
|
|
|
| for(int j = 0; j < m; j++){
|
| for(int i = 0; i < 2; i++){
|
| memcpy(xval, xkey, 20);//xval = xkey mod 2^160
|
| memset(xval + 20, 0, 44);//padding xval to 64 bytes
|
|
|
| SHA_CTX c;
|
| SHA1_Init(&c);
|
| SHA1_Update(&c, xval, 64);
|
|
|
| memcpy(x_out + j * 40 + i * 20, change_ByteOrder(c.h0), 4);
|
| memcpy(x_out + j * 40 + i * 20 + 4, change_ByteOrder(c.h1), 4);
|
| memcpy(x_out + j * 40 + i * 20 + 8, change_ByteOrder(c.h2), 4);
|
| memcpy(x_out + j * 40 + i * 20 + 12, change_ByteOrder(c.h3), 4);
|
| memcpy(x_out + j * 40 + i * 20 + 16, change_ByteOrder(c.h4), 4);//w_i
|
|
|
| BIGNUM * bn1 = BN_new();
|
| BIGNUM * bn2 = BN_new();
|
| BIGNUM * bn3 = BN_new();
|
| if(!bn1 || !bn2 || !bn3)
|
| TTCN_error("Key generation failed");
|
|
|
| BN_bin2bn(xkey, 20, bn1);//xkey
|
|
|
| BN_one(bn2);//1
|
|
|
| BN_add(bn3, bn1, bn2);//bn3 = xkey + 1
|
|
|
| BN_bin2bn(x_out + j * 40, 20, bn2);//w_i
|
|
|
| BN_add(bn1, bn3, bn2);//bn1 = xkey + 1 + w_i
|
|
|
| BN_bn2bin(bn1, dummy);
|
| for(int k = 0; k < 20; k++){
|
| if(BN_num_bytes(bn1) - 1 - k < 0)
|
| xkey[19 - k] = '\0';
|
| else
|
| xkey[19 - k] = dummy[BN_num_bytes(bn1) - 1 - k];
|
| }//xkey = (xkey + 1 + w_i) mod 2 ^ 160
|
|
|
| BN_free(bn1);
|
| BN_free(bn2);
|
| BN_free(bn3);
|
| }
|
| }
|
|
|
| Kencr = OCTETSTRING(16, x_out);
|
| OCTETSTRING Kaut = OCTETSTRING(16, x_out + 16);
|
| // PMK = OCTETSTRING(32, x_out + 32);
|
|
|
| return Kaut;
|
| }
|
|
|
| OCTETSTRING f__calc__AKA__Keys(const OCTETSTRING& pl_eap_identity, const OCTETSTRING& pl_AKA_K,const OCTETSTRING& pl_rand,OCTETSTRING& pl_AK,OCTETSTRING& pl_Kaut,OCTETSTRING& pl_Kencr)
|
| {
|
| const OCTETSTRING& xdout = pl_AKA_K ^ pl_rand;
|
| const OCTETSTRING& IK = xdout <<= 2;
|
| const OCTETSTRING& CK = xdout <<= 1;
|
| pl_AK = OCTETSTRING(6, ((const unsigned char*)xdout) + 3);
|
| pl_Kaut = f__calc__Kaut(pl_eap_identity + IK + CK,pl_Kencr);
|
| return xdout;
|
| }
|
| |
|
|
| void f__get__ServersPublicKey(const OCTETSTRING& pl_certificate, OCTETSTRING& pl_modules, OCTETSTRING& pl_exponent)
|
| {
|
| X509 *x;
|
| const unsigned char *cert = (const unsigned char *)pl_certificate;
|
|
|
| x = NULL;
|
|
|
| d2i_X509(&x, &cert, pl_certificate.lengthof());
|
| // X509_print_fp(stdout, x);
|
|
|
| if (x != NULL)
|
| {
|
| unsigned char *pkd = x->cert_info->key->public_key->data;
|
|
|
| if(pkd != NULL)
|
| {
|
| //int structlength = 0;
|
| int structlengthlength = 0;
|
| int moduleslength = 0;
|
| int moduleslengthlength = 0;
|
| int exponentlength = 0;
|
| int exponentlengthlength = 0;
|
| if(pkd[1] & 0x80)
|
| {
|
| structlengthlength = (pkd[1] & 0x7f);
|
| //structlength = oct2int((OCTETSTRING(structlengthlength, (const unsigned char *)(pkd + 2))));
|
| }
|
| //else
|
| //{
|
| //structlength = pkd[1];
|
| //}
|
| //type,length,type
|
| if(pkd[structlengthlength + 3] & 0x80)
|
| {
|
| moduleslengthlength = (pkd[structlengthlength + 3] & 0x7f);
|
| moduleslength = oct2int((OCTETSTRING(moduleslengthlength, (const unsigned char *)(pkd + structlengthlength + 4))));
|
| }
|
| else
|
| {
|
| moduleslength = pkd[structlengthlength + 3];
|
| }
|
| pl_modules = (OCTETSTRING(moduleslength, (const unsigned char *)(pkd + 4 + structlengthlength + moduleslengthlength)));
|
|
|
| if(pkd[moduleslength + structlengthlength + moduleslengthlength + 5] & 0x80)
|
| {
|
| exponentlengthlength = (pkd[moduleslength + structlengthlength + moduleslengthlength + 5] & 0x7f);
|
| exponentlength = oct2int((OCTETSTRING(exponentlengthlength, (const unsigned char *)(pkd + moduleslength + structlengthlength + moduleslengthlength + 6))));
|
| }
|
| else
|
| {
|
| exponentlength = pkd[moduleslength + structlengthlength + moduleslengthlength + 5];
|
| }
|
| pl_exponent = (OCTETSTRING(exponentlength, (const unsigned char *)(pkd + 6 + structlengthlength + moduleslengthlength + moduleslength + exponentlengthlength)));
|
| }
|
| }
|
| }
|
| #define MAX_MESSAGE_LENGTH 4096
|
|
|
|
|
|
|
|
|
| |
|
|
| void hmac_sha1(
|
| unsigned char *key,
|
| int key_length,
|
| unsigned char *data,
|
| int data_length,
|
| unsigned char *digest
|
| )
|
|
|
| {
|
| int b = 64; /* blocksize */
|
| unsigned char ipad = 0x36;
|
|
|
| unsigned char opad = 0x5c;
|
|
|
| unsigned char k0[64];
|
| unsigned char k0xorIpad[64];
|
| unsigned char step7data[64];
|
| unsigned char step5data[MAX_MESSAGE_LENGTH+128];
|
| unsigned char step8data[64+20];
|
| int i;
|
|
|
| for (i=0; i<64; i++)
|
| {
|
| k0[i] = 0x00;
|
| }
|
|
|
|
|
|
|
| if (key_length != b) /* Step 1 */
|
| {
|
| /* Step 2 */
|
| if (key_length > b)
|
| {
|
| SHA1(key, key_length, digest);
|
| for (i=0;i<20;i++)
|
| {
|
| k0[i]=digest[i];
|
| }
|
| }
|
| else if (key_length < b) /* Step 3 */
|
| {
|
| for (i=0; i<key_length; i++)
|
| {
|
| k0[i] = key[i];
|
| }
|
| }
|
| }
|
| else
|
| {
|
| for (i=0;i<b;i++)
|
| {
|
| k0[i] = key[i];
|
| }
|
| }
|
| /* Step 4 */
|
| for (i=0; i<64; i++)
|
| {
|
| k0xorIpad[i] = k0[i] ^ ipad;
|
| }
|
| /* Step 5 */
|
| for (i=0; i<64; i++)
|
| {
|
| step5data[i] = k0xorIpad[i];
|
| }
|
| for (i=0;i<data_length;i++)
|
| {
|
| step5data[i+64] = data[i];
|
| }
|
|
|
| /* Step 6 */
|
| SHA1(step5data, data_length+b, digest);
|
|
|
| /* Step 7 */
|
| for (i=0; i<64; i++)
|
| {
|
| step7data[i] = k0[i] ^ opad;
|
| }
|
|
|
|
|
| /* Step 8 */
|
| for (i=0;i<64;i++)
|
| {
|
| step8data[i] = step7data[i];
|
| }
|
| for (i=0;i<20;i++)
|
| {
|
| step8data[i+64] = digest[i];
|
| }
|
|
|
|
|
| /* Step 9 */
|
| SHA1(step8data, b+20, digest);
|
|
|
| }
|
|
|
|
|
|
|
| OCTETSTRING f__prf(const OCTETSTRING& pl_key, const OCTETSTRING& pl_prefix,
|
| const OCTETSTRING& pl_data, const INTEGER& result_length_inOctets)
|
| {
|
| unsigned char *key = (unsigned char*)(const unsigned char*)pl_key;
|
| int key_length = pl_key.lengthof();
|
| const unsigned char *prefix = (const unsigned char*)pl_prefix;
|
| int prefix_length = pl_prefix.lengthof();
|
| const unsigned char *data = (const unsigned char*)pl_data;
|
| int data_length = pl_data.lengthof();
|
| unsigned char r[MAX_MESSAGE_LENGTH*2+128];
|
| int r_length;
|
| unsigned char hmac_sha_result[20];
|
| unsigned char input_data[MAX_MESSAGE_LENGTH*2+128];
|
| int input_data_length;
|
| int i,j;
|
| r_length = 0;
|
|
|
| for (i=0; i<((result_length_inOctets*8+159)/160); i++)
|
| {
|
| for (j=0;j<prefix_length;j++)
|
| {
|
| input_data[j] = prefix[j];
|
| }
|
| input_data[prefix_length]= 0x00;
|
| for (j=0;j<data_length;j++)
|
| {
|
| input_data[prefix_length+j+1] = data[j];
|
| }
|
| input_data_length = prefix_length + data_length + 1;
|
|
|
| input_data[input_data_length] = (unsigned char)i;
|
| input_data_length++;
|
| input_data[input_data_length] = 0x00;
|
| OCTETSTRING vl_input(input_data_length,input_data);
|
| hmac_sha1(key, key_length, input_data, input_data_length,hmac_sha_result);
|
| for (j=0; j<20; j++)
|
| {
|
| r[r_length+j] = hmac_sha_result[j];
|
| }
|
| r_length = r_length+20;
|
| }
|
| OCTETSTRING result(result_length_inOctets,r);
|
| return result;
|
| }
|
|
|
|
|
|
|
|
|
|
|
| }
|