Class: EMV::APDU::CPS::SecureContext

Inherits:
Object
  • Object
show all
Defined in:
lib/emv/cps_apdu.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(k_enc = "\x00"*16, k_mac = "\x00"*16, k_dek = "\x00"*16, host_challenge = "\x00"*8) ⇒ SecureContext

Returns a new instance of SecureContext.



45
46
47
48
49
50
51
52
# File 'lib/emv/cps_apdu.rb', line 45

def initialize k_enc="\x00"*16, k_mac="\x00"*16, k_dek="\x00"*16, host_challenge="\x00"*8
  @k_enc = k_enc
  @k_mac = k_mac
  @k_dek = k_dek
  
  @host_challenge=host_challenge
  @level = :no_sec
end

Instance Attribute Details

#host_challengeObject

The challenge sent to the card, (Rterm)



17
18
19
# File 'lib/emv/cps_apdu.rb', line 17

def host_challenge
  @host_challenge
end

#initialize_responseObject

The card’s response to initialize update containing: kmc_id (Identifier of the KMC) csn (Chip Serial Number) kmc_version (Version Number of Master key (KMC)) sec_channel_proto_id (Identifier of Secure Channel Protocol) sequence_counter (Sequence Counter) challenge (Card challenge (r card)) cryptogram (Card Cryptogram)



34
35
36
# File 'lib/emv/cps_apdu.rb', line 34

def initialize_response
  @initialize_response
end

#k_dekObject

The Kdek key used in this session



14
15
16
# File 'lib/emv/cps_apdu.rb', line 14

def k_dek
  @k_dek
end

#k_encObject

The Kenc key used in this session



8
9
10
# File 'lib/emv/cps_apdu.rb', line 8

def k_enc
  @k_enc
end

#k_macObject

The Kmac key used in this session



11
12
13
# File 'lib/emv/cps_apdu.rb', line 11

def k_mac
  @k_mac
end

#levelObject

The security level established by the EXTERNAL_AUTH command According to CPS Table 19 One of:

:enc_and_mac
:mac
:no_sec


42
43
44
# File 'lib/emv/cps_apdu.rb', line 42

def level
  @level
end

#sku_dekObject

Returns the value of attribute sku_dek.



23
24
25
# File 'lib/emv/cps_apdu.rb', line 23

def sku_dek
  @sku_dek
end

#sku_encObject

The session key SKUenc



20
21
22
# File 'lib/emv/cps_apdu.rb', line 20

def sku_enc
  @sku_enc
end

#sku_macObject

Returns the value of attribute sku_mac.



22
23
24
# File 'lib/emv/cps_apdu.rb', line 22

def sku_mac
  @sku_mac
end

Instance Method Details

#calculate_c_mac(apdu) ⇒ Object

Calculate the C-MAC according to CP 5.4.2.2



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/emv/cps_apdu.rb', line 104

def calculate_c_mac apdu
  # data with placeholder for cmac
  data =  apdu.data
  mac_ =  apdu.cla +
          apdu.ins +
          apdu.p1  +
          apdu.p2 
  
  mac_ << apdu.data.length+8
  mac_ << data 
  if @c_mac # "prepend the c-mac computed for the previous command ..."
    mac_ = @c_mac + mac_ 
  end
  @c_mac = EMV::Crypto.retail_mac(sku_mac, mac_) 
  @c_mac  
end

#calculate_host_cryptogramObject

Calculates the host cryptogram according to CPS 3.2.6.6



96
97
98
99
100
101
# File 'lib/emv/cps_apdu.rb', line 96

def calculate_host_cryptogram
  mac_ = initialize_response.sequence_counter + 
         initialize_response.challenge +
         host_challenge
  EMV::Crypto.mac_for_personalization(sku_enc, mac_)
end

#check_card_cryptogramObject

Verify the cryptogram sent by the card according to: CPS 3.2.5.10



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/emv/cps_apdu.rb', line 74

def check_card_cryptogram
  mac_         = host_challenge + 
                 initialize_response.sequence_counter + 
                 initialize_response.challenge

  mac          = EMV::Crypto.mac_for_personalization(sku_enc, mac_)
  unless mac == initialize_response.cryptogram
    raise %Q{
Invalid MAC returned from card!
host challenge: #{ISO7816.b2s(host_challenge)}
card seq      : #{ISO7816.b2s(initialize_response.sequence_counter)}
card challenge: #{ISO7816.b2s(initialize_response.challenge)}
expected mac  : #{ISO7816.b2s(mac)}
recv mac      : #{ISO7816.b2s(initialize_response.cryptogram)}
k_enc         : #{ISO7816.b2s(k_enc)}
k_mac         : #{ISO7816.b2s(k_mac)}
k_dek         : #{ISO7816.b2s(k_dek)}
    }
  end
end

#encrypt(data) ⇒ Object

Encrypt data bytes according to CPS 5.5.2



137
138
139
140
141
142
# File 'lib/emv/cps_apdu.rb', line 137

def encrypt data
  data = EMV::Crypto.pad data
  cipher = OpenSSL::Cipher::Cipher.new("des-ede-cbc").encrypt
  cipher.key = sku_enc
  cipher.update data
end

#resetObject



128
129
130
131
132
133
134
# File 'lib/emv/cps_apdu.rb', line 128

def reset
  @c_mac = nil
  @store_data_seq_number = nil
  @sku_enc = nil
  @sku_mac = nil
  @initialize_response = nil
end

#store_data_seq_numberObject

Retrieve the current seq number, this also increments the counter.



122
123
124
125
126
# File 'lib/emv/cps_apdu.rb', line 122

def store_data_seq_number
  @store_data_seq_number ||= -1
  @store_data_seq_number += 1
  "" << @store_data_seq_number
end