Esempio n. 1
0
 def configure_profile(self, cfg):
     p = Profile(self, cfg['name'])
     p.add_local_id(id_type=cfg['loc_id'][0], data=cfg['loc_id'][1])
     p.add_remote_id(id_type=cfg['rem_id'][0], data=cfg['rem_id'][1])
     p.add_local_ts(**cfg['loc_ts'])
     p.add_remote_ts(**cfg['rem_ts'])
     p.add_responder(cfg['responder'])
     p.add_ike_transforms(cfg['ike_ts'])
     p.add_esp_transforms(cfg['esp_ts'])
     p.add_auth(**cfg['auth'])
     p.set_udp_encap(cfg['udp_encap'])
     p.set_ipsec_over_udp_port(cfg['ipsec_over_udp_port'])
     if 'lifetime_data' in cfg:
         p.set_lifetime_data(cfg['lifetime_data'])
     if 'tun_itf' in cfg:
         p.set_tunnel_interface(cfg['tun_itf'])
     p.add_vpp_config()
     return p
Esempio n. 2
0
class Ikev2Params(object):
    def config_params(self, params={}):
        ec = VppEnum.vl_api_ipsec_crypto_alg_t
        ei = VppEnum.vl_api_ipsec_integ_alg_t
        self.vpp_enums = {
            'AES-CBC-128': ec.IPSEC_API_CRYPTO_ALG_AES_CBC_128,
            'AES-CBC-192': ec.IPSEC_API_CRYPTO_ALG_AES_CBC_192,
            'AES-CBC-256': ec.IPSEC_API_CRYPTO_ALG_AES_CBC_256,
            'AES-GCM-16ICV-128': ec.IPSEC_API_CRYPTO_ALG_AES_GCM_128,
            'AES-GCM-16ICV-192': ec.IPSEC_API_CRYPTO_ALG_AES_GCM_192,
            'AES-GCM-16ICV-256': ec.IPSEC_API_CRYPTO_ALG_AES_GCM_256,
            'HMAC-SHA1-96': ei.IPSEC_API_INTEG_ALG_SHA1_96,
            'SHA2-256-128': ei.IPSEC_API_INTEG_ALG_SHA_256_128,
            'SHA2-384-192': ei.IPSEC_API_INTEG_ALG_SHA_384_192,
            'SHA2-512-256': ei.IPSEC_API_INTEG_ALG_SHA_512_256
        }

        is_natt = 'natt' in params and params['natt'] or False
        self.p = Profile(self, 'pr1')

        if 'auth' in params and params['auth'] == 'rsa-sig':
            auth_method = 'rsa-sig'
            work_dir = os.getenv('BR') + '/../src/plugins/ikev2/test/certs/'
            self.vapi.ikev2_set_local_key(key_file=work_dir +
                                          params['server-key'])

            client_file = work_dir + params['client-cert']
            server_pem = open(work_dir + params['server-cert']).read()
            client_priv = open(work_dir + params['client-key']).read()
            client_priv = load_pem_private_key(str.encode(client_priv), None,
                                               default_backend())
            self.peer_cert = x509.load_pem_x509_certificate(
                str.encode(server_pem), default_backend())
            self.p.add_auth(method='rsa-sig', data=str.encode(client_file))
            auth_data = None
        else:
            auth_data = b'$3cr3tpa$$w0rd'
            self.p.add_auth(method='shared-key', data=auth_data)
            auth_method = 'shared-key'
            client_priv = None

        self.p.add_local_id(id_type='fqdn', data=b'vpp.home')
        self.p.add_remote_id(id_type='fqdn', data=b'roadwarrior.example.com')
        self.p.add_local_ts(start_addr='10.10.10.0', end_addr='10.10.10.255')
        self.p.add_remote_ts(start_addr='10.0.0.0', end_addr='10.0.0.255')

        self.sa = IKEv2SA(self,
                          i_id=self.p.remote_id['data'],
                          r_id=self.p.local_id['data'],
                          id_type=self.p.local_id['id_type'],
                          natt=is_natt,
                          priv_key=client_priv,
                          auth_method=auth_method,
                          auth_data=auth_data,
                          local_ts=self.p.remote_ts,
                          remote_ts=self.p.local_ts)

        ike_crypto = ('AES-CBC', 32) if 'ike-crypto' not in params else\
            params['ike-crypto']
        ike_integ = 'HMAC-SHA1-96' if 'ike-integ' not in params else\
            params['ike-integ']
        ike_dh = '2048MODPgr' if 'ike-dh' not in params else params['ike-dh']

        esp_crypto = ('AES-CBC', 32) if 'esp-crypto' not in params else\
            params['esp-crypto']
        esp_integ = 'HMAC-SHA1-96' if 'esp-integ' not in params else\
            params['esp-integ']

        self.sa.set_ike_props(crypto=ike_crypto[0],
                              crypto_key_len=ike_crypto[1],
                              integ=ike_integ,
                              prf='PRF_HMAC_SHA2_256',
                              dh=ike_dh)
        self.sa.set_esp_props(crypto=esp_crypto[0],
                              crypto_key_len=esp_crypto[1],
                              integ=esp_integ)
Esempio n. 3
0
class TestResponder(VppTestCase):
    """ responder test """
    @classmethod
    def setUpClass(cls):
        import scapy.contrib.ikev2 as _ikev2
        globals()['ikev2'] = _ikev2
        super(TestResponder, cls).setUpClass()
        cls.create_pg_interfaces(range(2))
        for i in cls.pg_interfaces:
            i.admin_up()
            i.config_ip4()
            i.resolve_arp()

    @classmethod
    def tearDownClass(cls):
        super(TestResponder, cls).tearDownClass()

    def setUp(self):
        super(TestResponder, self).setUp()
        self.config_tc()

    def config_tc(self):
        self.p = Profile(self, 'pr1')
        self.p.add_auth(method='shared-key', data=b'$3cr3tpa$$w0rd')
        self.p.add_local_id(id_type='fqdn', data=b'vpp.home')
        self.p.add_remote_id(id_type='fqdn', data=b'roadwarrior.example.com')
        self.p.add_local_ts(start_addr=0x0a0a0a0, end_addr=0x0a0a0aff)
        self.p.add_remote_ts(start_addr=0xa000000, end_addr=0xa0000ff)
        self.p.add_vpp_config()

        self.sa = IKEv2SA(self,
                          i_id=self.p.remote_id['data'],
                          r_id=self.p.local_id['data'],
                          is_initiator=True,
                          auth_data=self.p.auth['data'],
                          id_type=self.p.local_id['id_type'],
                          local_ts=self.p.remote_ts,
                          remote_ts=self.p.local_ts)

        self.sa.set_ike_props(crypto='AES-CBC',
                              crypto_key_len=32,
                              integ='HMAC-SHA1-96',
                              prf='PRF_HMAC_SHA2_256',
                              dh='2048MODPgr')
        self.sa.set_esp_props(crypto='AES-CBC',
                              crypto_key_len=32,
                              integ='HMAC-SHA1-96')
        self.sa.generate_dh_data()

    def create_ike_msg(self, src_if, msg, sport=500, dport=500):
        return (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
                IP(src=src_if.remote_ip4, dst=src_if.local_ip4) /
                UDP(sport=sport, dport=dport) / msg)

    def send_sa_init(self):
        tr_attr = self.sa.ike_crypto_attr()
        trans = (
            ikev2.IKEv2_payload_Transform(transform_type='Encryption',
                                          transform_id=self.sa.ike_crypto,
                                          length=tr_attr[1],
                                          key_length=tr_attr[0]) /
            ikev2.IKEv2_payload_Transform(transform_type='Integrity',
                                          transform_id=self.sa.ike_integ) /
            ikev2.IKEv2_payload_Transform(
                transform_type='PRF', transform_id=self.sa.ike_prf_alg.name) /
            ikev2.IKEv2_payload_Transform(transform_type='GroupDesc',
                                          transform_id=self.sa.ike_dh))

        props = (ikev2.IKEv2_payload_Proposal(proposal=1,
                                              proto='IKEv2',
                                              trans_nb=4,
                                              trans=trans))

        self.sa.init_req_packet = (
            ikev2.IKEv2(init_SPI=self.sa.ispi,
                        flags='Initiator',
                        exch_type='IKE_SA_INIT') /
            ikev2.IKEv2_payload_SA(next_payload='KE', prop=props) /
            ikev2.IKEv2_payload_KE(next_payload='Nonce',
                                   group=self.sa.ike_dh,
                                   load=self.sa.dh_pub_key()) /
            ikev2.IKEv2_payload_Nonce(load=self.sa.i_nonce))

        ike_msg = self.create_ike_msg(self.pg0, self.sa.init_req_packet)
        self.pg0.add_stream(ike_msg)
        self.pg0.enable_capture()
        self.pg_start()
        capture = self.pg0.get_capture(1)
        self.verify_sa_init(capture[0])

    def send_sa_auth(self):
        tr_attr = self.sa.esp_crypto_attr()
        trans = (
            ikev2.IKEv2_payload_Transform(transform_type='Encryption',
                                          transform_id=self.sa.esp_crypto,
                                          length=tr_attr[1],
                                          key_length=tr_attr[0]) /
            ikev2.IKEv2_payload_Transform(transform_type='Integrity',
                                          transform_id=self.sa.esp_integ) /
            ikev2.IKEv2_payload_Transform(
                transform_type='Extended Sequence Number',
                transform_id='No ESN') /
            ikev2.IKEv2_payload_Transform(
                transform_type='Extended Sequence Number', transform_id='ESN'))

        props = (ikev2.IKEv2_payload_Proposal(proposal=1,
                                              proto='ESP',
                                              SPIsize=4,
                                              SPI=os.urandom(4),
                                              trans_nb=4,
                                              trans=trans))

        tsi, tsr = self.sa.generate_ts()
        plain = (ikev2.IKEv2_payload_IDi(
            next_payload='IDr', IDtype=self.sa.id_type, load=self.sa.i_id) /
                 ikev2.IKEv2_payload_IDr(next_payload='AUTH',
                                         IDtype=self.sa.id_type,
                                         load=self.sa.r_id) /
                 ikev2.IKEv2_payload_AUTH(
                     next_payload='SA', auth_type=2, load=self.sa.auth_data) /
                 ikev2.IKEv2_payload_SA(next_payload='TSi', prop=props) /
                 ikev2.IKEv2_payload_TSi(next_payload='TSr',
                                         number_of_TSs=len(tsi),
                                         traffic_selector=tsi) /
                 ikev2.IKEv2_payload_TSr(next_payload='Notify',
                                         number_of_TSs=len(tsr),
                                         traffic_selector=tsr) /
                 ikev2.IKEv2_payload_Notify(type='INITIAL_CONTACT'))
        encr = self.sa.encrypt(raw(plain))

        trunc_len = self.sa.ike_integ_alg.trunc_len
        plen = len(encr) + len(ikev2.IKEv2_payload_Encrypted()) + trunc_len
        tlen = plen + len(ikev2.IKEv2())

        sk_p = ikev2.IKEv2_payload_Encrypted(next_payload='IDi',
                                             length=plen,
                                             load=encr)
        sa_auth = (ikev2.IKEv2(init_SPI=self.sa.ispi,
                               resp_SPI=self.sa.rspi,
                               length=tlen,
                               flags='Initiator',
                               exch_type='IKE_AUTH',
                               id=1))
        sa_auth /= sk_p

        integ_data = raw(sa_auth)
        hmac_data = self.sa.compute_hmac(self.sa.ike_integ_alg.mod(),
                                         self.sa.my_authkey, integ_data)
        sa_auth = sa_auth / Raw(hmac_data[:trunc_len])
        assert (len(sa_auth) == tlen)

        packet = self.create_ike_msg(self.pg0, sa_auth)
        self.pg0.add_stream(packet)
        self.pg0.enable_capture()
        self.pg_start()
        capture = self.pg0.get_capture(1)
        self.verify_sa_auth(capture[0])

    def verify_sa_init(self, packet):
        ih = packet[ikev2.IKEv2]
        self.assertEqual(ih.exch_type, 34)
        self.assertTrue('Response' in ih.flags)
        self.assertEqual(ih.init_SPI, self.sa.ispi)
        self.assertNotEqual(ih.resp_SPI, 0)
        self.sa.rspi = ih.resp_SPI
        try:
            sa = ih[ikev2.IKEv2_payload_SA]
            self.sa.r_nonce = ih[ikev2.IKEv2_payload_Nonce].load
            self.sa.r_dh_data = ih[ikev2.IKEv2_payload_KE].load
        except AttributeError as e:
            self.logger.error("unexpected reply: SA/Nonce/KE payload found!")
            raise
        self.sa.complete_dh_data()
        self.sa.calc_keys()
        self.sa.auth_init()

    def verify_sa_auth(self, packet):
        try:
            ike = packet[ikev2.IKEv2]
            ep = packet[ikev2.IKEv2_payload_Encrypted]
        except KeyError as e:
            self.logger.error("unexpected reply: no IKEv2/Encrypt payload!")
            raise
        plain = self.sa.hmac_and_decrypt(ike)
        self.sa.calc_child_keys()

    def verify_child_sas(self):
        sas = self.vapi.ipsec_sa_dump()
        self.assertEqual(len(sas), 2)
        sa0 = sas[0].entry
        sa1 = sas[1].entry
        c = self.sa.child_sas[0]

        # verify crypto keys
        self.assertEqual(sa0.crypto_key.length, len(c.sk_er))
        self.assertEqual(sa1.crypto_key.length, len(c.sk_ei))
        self.assertEqual(sa0.crypto_key.data[:len(c.sk_er)], c.sk_er)
        self.assertEqual(sa1.crypto_key.data[:len(c.sk_ei)], c.sk_ei)

        # verify integ keys
        self.assertEqual(sa0.integrity_key.length, len(c.sk_ar))
        self.assertEqual(sa1.integrity_key.length, len(c.sk_ai))
        self.assertEqual(sa0.integrity_key.data[:len(c.sk_ar)], c.sk_ar)
        self.assertEqual(sa1.integrity_key.data[:len(c.sk_ai)], c.sk_ai)

    def test_responder(self):
        self.send_sa_init()
        self.send_sa_auth()
        self.verify_child_sas()