def checkTKIPtestVector(self, description, key, ta, iv, plainText, cipherText): """ Process TKIP encryption test vectors (no MIC) """ print '%s %s %s'%('='*((54-len(description))/2),description,'='*((54-len(description))/2)) # Convert from octet lists to string key = a2b_p(key) ta = a2b_p(ta) iv = a2b_p(iv) pt = a2b_p(plainText) kct = a2b_p(cipherText) mixer = TKIP_Mixer(key,ta) rc4key = mixer.newKey(iv) alg = TKIP_encr(key) alg.setTA(ta) print 'key: %s'%b2a_p(key)[9:] print 'rc4Key %s'%b2a_p(rc4key)[9:] # calculated print 'ta: %s'%b2a_p(ta)[9:] print 'iv: %s'%b2a_p(iv)[9:] print 'pt: %s'%b2a_p(pt)[9:] print 'kct: %s'%b2a_p(kct)[9:] ct = alg.encrypt(pt, iv) print 'ct: %s'%b2a_p(ct)[9:] cpt = alg.decrypt(kct) print 'cpt: %s'%b2a_p(cpt)[9:] print '========================================================' self.assertEqual( ct, kct ) alg.setKey(key) dct = alg.decrypt( ct ) self.assertEqual( dct, pt )
def xtestTKIP_Mixer_TV_values(self): """ Test using vectors from IEEE 802.11TGi D2.4.2 """ for testCase in TKIP_TestVector: description = testCase['testCase'] tk = a2b_p(testCase['TK']) ta = a2b_p(testCase['TA']) pn = testCase['PN'] pnField = pack('<Q', pn)[:6] print '===========================================================' print 'testCase:%s'%description print 'TK: %s'%b2a_p(tk)[9:] print 'TA: %s'%b2a_p(ta)[9:] keyId = 0 eh1 = chr((ord(pnField[1])|0x20)&0x7f) eh = pnField[0]+eh1+pnField[1]+chr((keyId<<6)|0x20)+pnField[2:] print 'EncHdr: %s (with KeyId=0)' % b2a_p(eh)[9:] print 'PNfield: %s' % b2a_p(pnField)[9:] print 'PNvalue: 0x%06X' % pn print 'TSC?: [0x%04x, 0x%04x, 0x%04x]' % (unpack('<H',pnField[0:2])[0],\ unpack('<H',pnField[2:4])[0],unpack('<H',pnField[4:6])[0]) mixer = TKIP_Mixer(tk,ta) newRC4Key = mixer.newKey(pnField) p1kstring = ''.join([pack('>H',i) for i in mixer.phase1Key]) # a list of int's print 'TTAK: [0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x]' % (mixer.phase1Key[0], \ mixer.phase1Key[1],mixer.phase1Key[2],mixer.phase1Key[3],mixer.phase1Key[4]) print 'P1K: %s'%b2a_p(p1kstring)[9:] print 'RC4Key: %s' % b2a_p( newRC4Key )[9:] print 'kRC4Key: %s' % b2a_p( a2b_p(testCase['RC4KEY']))[9:] self.assertEqual(newRC4Key, a2b_p(testCase['RC4KEY'])) print '==========================================================='
def __init__(self, key=None, transmitterAddress=None, keyID=None): """ Initialize TKIP_encr, key -> octet string for key """ assert(keyID == 0 or keyID == None), 'keyID should be zero in TKIP' self.keyId = 0 self.name = 'TKIP_encr' self.strength = 128 self.encryptHeaderSize = 8 # used to skip octets on decrypt self.arc4 = ARC4() # base algorithm self.keyMixer = TKIP_Mixer(key, transmitterAddress) if key != None: # normally in base init, uses adjusted keySize self.setKey(key) if transmitterAddress != None: self.setTA(transmitterAddress)
def testTKIP_Mixer_KnowValues(self): """ Test using vectors from IEEE 802.11TGi D2.4.2 """ for testCase in TKIP_MixerTestCases: description = testCase["testCase"] tk = a2b_p(testCase["TK"]) ta = a2b_p(testCase["TA"]) iv32 = a2b_p(testCase["IV32"]) # last 4 octets of PN/IV field iv16 = a2b_p(testCase["IV16"]) # NOTE - iv16 and iv32 are confused notation from early drafts # may not match notation in the future pnField = iv16[1] + iv16[0] + iv32[3] + iv32[2] + iv32[1] + iv32[0] pn = unpack("<Q", pnField + 2 * chr(0))[0] knownP1key = a2b_p(testCase["P1K"]) knownRC4Key = a2b_p(testCase["RC4KEY"]) print "===========================================================" print "testCase:%s" % description print "TK: %s" % b2a_p(tk)[9:] print "TA: %s" % b2a_p(ta)[9:] print "IV32: %s" % b2a_p(iv32)[9:] print "IV16: %s" % b2a_p(iv16)[9:] keyId = 0 eh1 = chr((ord(pnField[1]) | 0x20) & 0x7F) eh = pnField[0] + eh1 + pnField[1] + chr((keyId << 6) | 0x20) + pnField[2:] print "EncHdr: %s (with KeyId=0)" % b2a_p(eh)[9:] print "PNfield: %s" % b2a_p(pnField)[9:] print "PNvalue: hex 0x%012X decimal %d" % (pn, pn) # print 'TSC: [0x%04x, 0x%04x, 0x%04x]' % (unpack('<H',pnField[0:2])[0],\ # unpack('<H',pnField[2:4])[0],unpack('<H',pnField[4:6])[0]) mixer = TKIP_Mixer(tk, ta) newRC4Key = mixer.newKey(pnField) p1kstring = "".join([pack(">H", i) for i in mixer.phase1Key]) # a list of int's print "TTAK: [0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x]" % ( mixer.phase1Key[0], mixer.phase1Key[1], mixer.phase1Key[2], mixer.phase1Key[3], mixer.phase1Key[4], ) print "P1K: %s" % b2a_p(p1kstring)[9:] # print 'knownP1K:%s'%b2a_p(knownP1key)[9:] self.assertEqual(p1kstring, knownP1key), "Phase1 Keys dont match" print "RC4Key: %s" % b2a_p(newRC4Key)[9:] # print 'knownRC4Key: %s'% b2a_p(knownRC4Key)[9:] self.assertEqual(newRC4Key, knownRC4Key), "Final Key does not match" print "==========================================================="
def testTKIP_Mixer_KnowValues(self): """ Test using vectors from IEEE 802.11TGi D2.4.2 """ for testCase in TKIP_MixerTestCases: description = testCase['testCase'] tk = a2b_p(testCase['TK']) ta = a2b_p(testCase['TA']) iv32 = a2b_p(testCase['IV32']) # last 4 octets of PN/IV field iv16 = a2b_p(testCase['IV16']) # NOTE - iv16 and iv32 are confused notation from early drafts # may not match notation in the future pnField = iv16[1] + iv16[0] + iv32[3] + iv32[2] + iv32[1] + iv32[0] pn = unpack('<Q', pnField + 2 * chr(0))[0] knownP1key = a2b_p(testCase['P1K']) knownRC4Key = a2b_p(testCase['RC4KEY']) print '===========================================================' print 'testCase:%s' % description print 'TK: %s' % b2a_p(tk)[9:] print 'TA: %s' % b2a_p(ta)[9:] print 'IV32: %s' % b2a_p(iv32)[9:] print 'IV16: %s' % b2a_p(iv16)[9:] keyId = 0 eh1 = chr((ord(pnField[1]) | 0x20) & 0x7f) eh = pnField[0] + eh1 + pnField[1] + chr((keyId << 6) | 0x20) + pnField[2:] print 'EncHdr: %s (with KeyId=0)' % b2a_p(eh)[9:] print 'PNfield: %s' % b2a_p(pnField)[9:] print 'PNvalue: hex 0x%012X decimal %d' % (pn, pn) #print 'TSC: [0x%04x, 0x%04x, 0x%04x]' % (unpack('<H',pnField[0:2])[0],\ # unpack('<H',pnField[2:4])[0],unpack('<H',pnField[4:6])[0]) mixer = TKIP_Mixer(tk, ta) newRC4Key = mixer.newKey(pnField) p1kstring = ''.join([pack('>H', i) for i in mixer.phase1Key]) # a list of int's print 'TTAK: [0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x]' % (mixer.phase1Key[0], \ mixer.phase1Key[1],mixer.phase1Key[2],mixer.phase1Key[3],mixer.phase1Key[4]) print 'P1K: %s' % b2a_p(p1kstring)[9:] #print 'knownP1K:%s'%b2a_p(knownP1key)[9:] self.assertEqual(p1kstring, knownP1key), 'Phase1 Keys dont match' print 'RC4Key: %s' % b2a_p(newRC4Key)[9:] #print 'knownRC4Key: %s'% b2a_p(knownRC4Key)[9:] self.assertEqual(newRC4Key, knownRC4Key), 'Final Key does not match' print '==========================================================='
def xtestGunarExample1(self): """ Test example from Gunnar 2003-01-27 """ tk1 = a2b_p( "A9 90 6D C8 3E 78 92 3F 86 04 E9 9E F6 CD BA BB" ) ta = a2b_p( "50 30 F1 84 44 08" ) iv32 = a2b_p( "B5039776" ) # [transmitted as B5 03 97 76] iv16 = a2b_p( "E70C" ) p1k = a2b_p( "26D5 F1E1 2A59 2021 0E8E" ) rc4Key = a2b_p( "E7 67 0C 68 15 E0 2E 3F 1C 15 92 92 D4 E2 78 82" ) mixer = TKIP_Mixer(tk1,ta) newRC4Key = mixer.newKey(iv16+iv32) print "=== Gunnar Example ===" print "rc4Key = ", b2a_p( rc4Key ) print "newRC4Key = ", b2a_p( newRC4Key ) print "knownp1K = ", b2a_p( p1k ) print "calcp1K = %04X %04X %04x %04x %04x" % (mixer.phase1Key[0],mixer.phase1Key[1],mixer.phase1Key[2],mixer.phase1Key[3],mixer.phase1Key[4]) self.assertEqual(rc4Key,newRC4Key)
def xtestTKIP_Mixer_TV_values(self): """ Test using vectors from IEEE 802.11TGi D2.4.2 """ for testCase in TKIP_TestVector: description = testCase["testCase"] tk = a2b_p(testCase["TK"]) ta = a2b_p(testCase["TA"]) pn = testCase["PN"] pnField = pack("<Q", pn)[:6] print "===========================================================" print "testCase:%s" % description print "TK: %s" % b2a_p(tk)[9:] print "TA: %s" % b2a_p(ta)[9:] keyId = 0 eh1 = chr((ord(pnField[1]) | 0x20) & 0x7F) eh = pnField[0] + eh1 + pnField[1] + chr((keyId << 6) | 0x20) + pnField[2:] print "EncHdr: %s (with KeyId=0)" % b2a_p(eh)[9:] print "PNfield: %s" % b2a_p(pnField)[9:] print "PNvalue: 0x%06X" % pn print "TSC?: [0x%04x, 0x%04x, 0x%04x]" % ( unpack("<H", pnField[0:2])[0], unpack("<H", pnField[2:4])[0], unpack("<H", pnField[4:6])[0], ) mixer = TKIP_Mixer(tk, ta) newRC4Key = mixer.newKey(pnField) p1kstring = "".join([pack(">H", i) for i in mixer.phase1Key]) # a list of int's print "TTAK: [0x%04x, 0x%04x, 0x%04x, 0x%04x, 0x%04x]" % ( mixer.phase1Key[0], mixer.phase1Key[1], mixer.phase1Key[2], mixer.phase1Key[3], mixer.phase1Key[4], ) print "P1K: %s" % b2a_p(p1kstring)[9:] print "RC4Key: %s" % b2a_p(newRC4Key)[9:] print "kRC4Key: %s" % b2a_p(a2b_p(testCase["RC4KEY"]))[9:] self.assertEqual(newRC4Key, a2b_p(testCase["RC4KEY"])) print "==========================================================="
def __init__(self, key=None, transmitterAddress=None, keyID=None): """ Initialize TKIP_encr, key -> octet string for key """ assert(keyID==0 or keyID==None), 'keyID should be zero in TKIP' self.keyId = 0 self.name = 'TKIP_encr' self.strength = 128 self.encryptHeaderSize = 8 # used to skip octets on decrypt self.arc4 = ARC4() # base algorithm self.keyMixer = TKIP_Mixer(key,transmitterAddress) if key != None: # normally in base init, uses adjusted keySize self.setKey(key) if transmitterAddress!=None: self.setTA(transmitterAddress)
def checkTKIPtestVector(self, description, key, ta, iv, plainText, cipherText): """ Process TKIP encryption test vectors (no MIC) """ print '%s %s %s' % ('=' * ((54 - len(description)) / 2), description, '=' * ((54 - len(description)) / 2)) # Convert from octet lists to string key = a2b_p(key) ta = a2b_p(ta) iv = a2b_p(iv) pt = a2b_p(plainText) kct = a2b_p(cipherText) mixer = TKIP_Mixer(key, ta) rc4key = mixer.newKey(iv) alg = TKIP_encr(key) alg.setTA(ta) print 'key: %s' % b2a_p(key)[9:] print 'rc4Key %s' % b2a_p(rc4key)[9:] # calculated print 'ta: %s' % b2a_p(ta)[9:] print 'iv: %s' % b2a_p(iv)[9:] print 'pt: %s' % b2a_p(pt)[9:] print 'kct: %s' % b2a_p(kct)[9:] ct = alg.encrypt(pt, iv) print 'ct: %s' % b2a_p(ct)[9:] cpt = alg.decrypt(kct) print 'cpt: %s' % b2a_p(cpt)[9:] print '========================================================' self.assertEqual(ct, kct) alg.setKey(key) dct = alg.decrypt(ct) self.assertEqual(dct, pt)
def xtestTKIP_Mixer_Sequence(self): """ Test TKIP Mixing using alternate calling approaches """ key = 16 * chr(0) ta = 6 * chr(0) tscOctets = 6 * chr(0) keyMixer = TKIP_Mixer(key) keyMixer.setTA(ta) newKey = keyMixer.newKey(tscOctets) keyMixer = TKIP_Mixer() keyMixer.setTA(ta) keyMixer.setKey(key) newKey = keyMixer.newKey(tscOctets) keyMixer = TKIP_Mixer(transmitterAddress=ta) keyMixer.setKey(key) newKey = keyMixer.newKey(tscOctets)
class TKIP_encr: """ TKIP Stream Cipher Algorithm without the Michael integrity check TKIP encryption on an MPDU using WEP with a longer 'iv' and the TKIP key mixing algorithm . This does NOT include the Michael integrity algorithm that operates on the MSDU data. """ def __init__(self, key=None, transmitterAddress=None, keyID=None): """ Initialize TKIP_encr, key -> octet string for key """ assert(keyID==0 or keyID==None), 'keyID should be zero in TKIP' self.keyId = 0 self.name = 'TKIP_encr' self.strength = 128 self.encryptHeaderSize = 8 # used to skip octets on decrypt self.arc4 = ARC4() # base algorithm self.keyMixer = TKIP_Mixer(key,transmitterAddress) if key != None: # normally in base init, uses adjusted keySize self.setKey(key) if transmitterAddress!=None: self.setTA(transmitterAddress) def setKey(self, key, ta=None): """ Set key, key string is 16 octets long """ self.keyMixer.setKey(key) if ta!=None: self.setTA(ta) def setTA(self, transmitterAddress): """ Set the transmitter address """ self.keyMixer.setTA(transmitterAddress) def _getIVandKeyID(self, cipherText): """ Parse the TKIP header to get iv and set KeyID iv is returned as octet string and is little-endian!!! """ assert(ord(cipherText[3])& 0x20),'extIV SHOULD be set in TKIP header' self.setCurrentKeyID = (ord(cipherText[3])&0xC0)>>6 return cipherText[:3] + cipherText[5:9] # note iv octets are little-endian!!! def _makeARC4key(self, tscOctets, keyID=0): """ Make an ARC4 key from TKIP Sequence Counter Octets (little-endian) """ if keyID!=0 : raise 'TKIP expects keyID of zero' print "tscOctets in tkmixer=",b2a_p(tscOctets) newKey = self.keyMixer.newKey(tscOctets) print "newKey=", b2a_p(newKey) return newKey def encrypt(self, plainText, iv): """ Encrypt a string and return a binary string iv is 6 octets of little-endian encoded pn """ assert(len(iv)==6),'TKIP bad IV size on encryption' self.pnField = iv self.arc4.setKey( self._makeARC4key(iv) ) eh1 = chr((ord(iv[0])|0x20)&0x7f) encryptionHeader = iv[0] + eh1 + iv[1] + chr((self.keyId<<6)|0x20) + iv[2:] crc = pack('<I', crc32(plainText) ) cipherText = encryptionHeader + self.arc4.encrypt(plainText+crc) return cipherText def decrypt(self, cipherText): """ Decrypt a WEP packet, assumes WEP 4 byte header on packet """ assert(ord(cipherText[3])& 0x20),'extIV SHOULD be set in TKIP header' self.setCurrentKeyID = (ord(cipherText[3])&0xC0)>>6 iv = cipherText[0]+cipherText[2]+cipherText[4:8] self.pnField = iv self.arc4.setKey( self._makeARC4key(iv) ) plainText = self.arc4.decrypt(cipherText[self.encryptHeaderSize:]) if plainText[-4:] != pack('<I',crc32(plainText[:-4])): # check data integrity raise IntegrityCheckError, 'WEP CRC Integrity Check Error' return plainText[:-4]
class TKIP_encr: """ TKIP Stream Cipher Algorithm without the Michael integrity check TKIP encryption on an MPDU using WEP with a longer 'iv' and the TKIP key mixing algorithm . This does NOT include the Michael integrity algorithm that operates on the MSDU data. """ def __init__(self, key=None, transmitterAddress=None, keyID=None): """ Initialize TKIP_encr, key -> octet string for key """ assert(keyID == 0 or keyID == None), 'keyID should be zero in TKIP' self.keyId = 0 self.name = 'TKIP_encr' self.strength = 128 self.encryptHeaderSize = 8 # used to skip octets on decrypt self.arc4 = ARC4() # base algorithm self.keyMixer = TKIP_Mixer(key, transmitterAddress) if key != None: # normally in base init, uses adjusted keySize self.setKey(key) if transmitterAddress != None: self.setTA(transmitterAddress) def setKey(self, key, ta=None): """ Set key, key string is 16 octets long """ self.keyMixer.setKey(key) if ta != None: self.setTA(ta) def setTA(self, transmitterAddress): """ Set the transmitter address """ self.keyMixer.setTA(transmitterAddress) def _getIVandKeyID(self, cipherText): """ Parse the TKIP header to get iv and set KeyID iv is returned as octet string and is little-endian!!! """ assert(ord(cipherText[3]) & 0x20), 'extIV SHOULD be set in TKIP header' self.setCurrentKeyID = (ord(cipherText[3]) & 0xC0) >> 6 return cipherText[:3] + cipherText[5:9] # note iv octets are little-endian!!! def _makeARC4key(self, tscOctets, keyID=0): """ Make an ARC4 key from TKIP Sequence Counter Octets (little-endian) """ if keyID != 0: raise 'TKIP expects keyID of zero' print("tscOctets in tkmixer=", b2a_p(tscOctets)) newKey = self.keyMixer.newKey(tscOctets) print("newKey=", b2a_p(newKey)) return newKey def encrypt(self, plainText, iv): """ Encrypt a string and return a binary string iv is 6 octets of little-endian encoded pn """ assert(len(iv) == 6), 'TKIP bad IV size on encryption' self.pnField = iv self.arc4.setKey(self._makeARC4key(iv)) eh1 = chr((ord(iv[0]) | 0x20) & 0x7f) encryptionHeader = iv[0] + eh1 + iv[1] + chr((self.keyId << 6) | 0x20) + iv[2:] crc = pack('<I', crc32(plainText)) cipherText = encryptionHeader + self.arc4.encrypt(plainText + crc) return cipherText def decrypt(self, cipherText): """ Decrypt a WEP packet, assumes WEP 4 byte header on packet """ assert(ord(cipherText[3]) & 0x20), 'extIV SHOULD be set in TKIP header' self.setCurrentKeyID = (ord(cipherText[3]) & 0xC0) >> 6 iv = cipherText[0] + cipherText[2] + cipherText[4:8] self.pnField = iv self.arc4.setKey(self._makeARC4key(iv)) plainText = self.arc4.decrypt(cipherText[self.encryptHeaderSize:]) if plainText[-4:] != pack('<I', crc32(plainText[:-4])): # check data integrity raise IntegrityCheckError, 'WEP CRC Integrity Check Error' return plainText[:-4]
def xtestTKIP_Mixer_Sequence(self): """ Test TKIP Mixing using alternate calling approaches """ key = 16*chr(0) ta = 6*chr(0) tscOctets = 6*chr(0) keyMixer = TKIP_Mixer(key) keyMixer.setTA(ta) newKey = keyMixer.newKey(tscOctets) keyMixer = TKIP_Mixer() keyMixer.setTA(ta) keyMixer.setKey(key) newKey = keyMixer.newKey(tscOctets) keyMixer = TKIP_Mixer(transmitterAddress=ta) keyMixer.setKey(key) newKey = keyMixer.newKey(tscOctets)