blob: 3bcd74e573b37f3fd91e4693bf56c73aa318d3d4 [file] [log] [blame]
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000-2019 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;
}
}