Coverage for /root/GitHubProjects/impacket/impacket/crypto.py: 69%

# Coverage for /root/GitHubProjects/impacket/impacket/crypto.py : 69%

## 156 statements

Hot-keys on this page

r m x p toggle line displays

j k next/prev highlighted chunk

0 (zero) top of page

1 (one) first highlighted chunk

1# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved.

2#

3# This software is provided under under a slightly modified version

4# of the Apache Software License. See the accompanying LICENSE file

5# for more information.

6#

7# Author: Alberto Solino (beto@coresecurity.com)

8#

9# Description:

10# RFC 4493 implementation (https://www.ietf.org/rfc/rfc4493.txt)

11# RFC 4615 implementation (https://www.ietf.org/rfc/rfc4615.txt)

12#

13# NIST SP 800-108 Section 5.1, with PRF HMAC-SHA256 implementation

14# (https://tools.ietf.org/html/draft-irtf-cfrg-kdf-uses-00#ref-SP800-108)

15#

16# [MS-LSAD] Section 5.1.2

17# [MS-SAMR] Section 2.2.11.1.1

18

19 from __future__ import division

20 from __future__ import print_function

21 from impacket import LOG

22 try:

23 from Cryptodome.Cipher import DES, AES

24 except Exception:

25 LOG.error("Warning: You don't have any crypto installed. You need pycryptodomex")

26 LOG.error("See https://pypi.org/project/pycryptodomex/")

27 from struct import pack, unpack

28 from impacket.structure import Structure

29 import hmac, hashlib

30 from six import b

31

32 def Generate_Subkey(K):

33

34# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

35# + Algorithm Generate_Subkey +

36# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

37# + +

38# + Input : K (128-bit key) +

39# + Output : K1 (128-bit first subkey) +

40# + K2 (128-bit second subkey) +

41# +-------------------------------------------------------------------+

42# + +

43# + Constants: const_Zero is 0x00000000000000000000000000000000 +

44# + const_Rb is 0x00000000000000000000000000000087 +

45# + Variables: L for output of AES-128 applied to 0^128 +

46# + +

47# + Step 1. L := AES-128(K, const_Zero); +

48# + Step 2. if MSB(L) is equal to 0 +

49# + then K1 := L << 1; +

50# + else K1 := (L << 1) XOR const_Rb; +

51# + Step 3. if MSB(K1) is equal to 0 +

52# + then K2 := K1 << 1; +

53# + else K2 := (K1 << 1) XOR const_Rb; +

54# + Step 4. return K1, K2; +

55# + +

56# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

57

58 AES_128 = AES.new(K, AES.MODE_ECB)

59

60 L = AES_128.encrypt(bytes(bytearray(16)))

61

62 LHigh = unpack('>Q',L[:8])[0]

63 LLow = unpack('>Q',L[8:])[0]

64

65 K1High = ((LHigh << 1) | ( LLow >> 63 )) & 0xFFFFFFFFFFFFFFFF

66 K1Low = (LLow << 1) & 0xFFFFFFFFFFFFFFFF

67

68 if (LHigh >> 63):

69 K1Low ^= 0x87

70

71 K2High = ((K1High << 1) | (K1Low >> 63)) & 0xFFFFFFFFFFFFFFFF

72 K2Low = ((K1Low << 1)) & 0xFFFFFFFFFFFFFFFF

73

74 if (K1High >> 63):

75 K2Low ^= 0x87

76

77 K1 = bytearray(pack('>QQ', K1High, K1Low))

78 K2 = bytearray(pack('>QQ', K2High, K2Low))

79

80 return K1, K2

81

82 def XOR_128(N1,N2):

83

84 J = bytearray()

85 for i in range(len(N1)):

86 #J.append(indexbytes(N1,i) ^ indexbytes(N2,i))

87 J.append(N1[i] ^ N2[i])

88 return J

89

90 def PAD(N):

91 padLen = 16-len(N)

92 return N + b'\x80' + b'\x00'*(padLen-1)

93

94 def AES_CMAC(K, M, length):

95

96# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

97# + Algorithm AES-CMAC +

98# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

99# + +

100# + Input : K ( 128-bit key ) +

101# + : M ( message to be authenticated ) +

102# + : len ( length of the message in octets ) +

103# + Output : T ( message authentication code ) +

104# + +

105# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

106# + Constants: const_Zero is 0x00000000000000000000000000000000 +

107# + const_Bsize is 16 +

108# + +

109# + Variables: K1, K2 for 128-bit subkeys +

110# + M_i is the i-th block (i=1..ceil(len/const_Bsize)) +

111# + M_last is the last block xor-ed with K1 or K2 +

112# + n for number of blocks to be processed +

113# + r for number of octets of last block +

114# + flag for denoting if last block is complete or not +

115# + +

116# + Step 1. (K1,K2) := Generate_Subkey(K); +

117# + Step 2. n := ceil(len/const_Bsize); +

118# + Step 3. if n = 0 +

119# + then +

120# + n := 1; +

121# + flag := false; +

122# + else +

123# + if len mod const_Bsize is 0 +

124# + then flag := true; +

125# + else flag := false; +

126# + +

127# + Step 4. if flag is true +

128# + then M_last := M_n XOR K1; +

129# + else M_last := padding(M_n) XOR K2; +

130# + Step 5. X := const_Zero; +

131# + Step 6. for i := 1 to n-1 do +

132# + begin +

133# + Y := X XOR M_i; +

134# + X := AES-128(K,Y); +

135# + end +

136# + Y := M_last XOR X; +

137# + T := AES-128(K,Y); +

138# + Step 7. return T; +

139# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

140

141 const_Bsize = 16

142 const_Zero = bytearray(16)

143

144 AES_128= AES.new(K, AES.MODE_ECB)

145 M = bytearray(M[:length])

146 K1, K2 = Generate_Subkey(K)

147 n = len(M)//const_Bsize

148

149 if n == 0:

150 n = 1

151 flag = False

152 else:

153 if (length % const_Bsize) == 0:

154 flag = True

155 else:

156 n += 1

157 flag = False

158

159 M_n = M[(n-1)*const_Bsize:]

160 if flag is True:

161 M_last = XOR_128(M_n,K1)

162 else:

163 M_last = XOR_128(PAD(M_n),K2)

164

165 X = const_Zero

166 for i in range(n-1):

167 M_i = M[(i)*const_Bsize:][:16]

168 Y = XOR_128(X, M_i)

169 X = bytearray(AES_128.encrypt(bytes(Y)))

170 Y = XOR_128(M_last, X)

171 T = AES_128.encrypt(bytes(Y))

172

173 return T

174

175 def AES_CMAC_PRF_128(VK, M, VKlen, Mlen):

176# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

177# + AES-CMAC-PRF-128 +

178# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

179# + +

180# + Input : VK (Variable-length key) +

181# + : M (Message, i.e., the input data of the PRF) +

182# + : VKlen (length of VK in octets) +

183# + : len (length of M in octets) +

184# + Output : PRV (128-bit Pseudo-Random Variable) +

185# + +

186# +-------------------------------------------------------------------+

187# + Variable: K (128-bit key for AES-CMAC) +

188# + +

189# + Step 1. If VKlen is equal to 16 +

190# + Step 1a. then +

191# + K := VK; +

192# + Step 1b. else +

193# + K := AES-CMAC(0^128, VK, VKlen); +

194# + Step 2. PRV := AES-CMAC(K, M, len); +

195# + return PRV; +

196# + +

197# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

198 if VKlen == 16:

199 K = VK

200 else:

201 K = AES_CMAC(bytes(bytearray(16)), VK, VKlen)

202

203 PRV = AES_CMAC(K, M, Mlen)

204

205 return PRV

206

207 def KDF_CounterMode(KI, Label, Context, L):

208# Implements NIST SP 800-108 Section 5.1, with PRF HMAC-SHA256

209# https://tools.ietf.org/html/draft-irtf-cfrg-kdf-uses-00#ref-SP800-108

210# Fixed values:

211# 1. h - The length of the output of the PRF in bits, and

212# 2. r - The length of the binary representation of the counter i.

213# Input: KI, Label, Context, and L.

214# Process:

215# 1. n := [L/h]

216# 2. If n > 2r-1, then indicate an error and stop.

217# 3. result(0):= empty .

218# 4. For i = 1 to n, do

219# a. K(i) := PRF (KI, [i]2 || Label || 0x00 || Context || [L]2)

220# b. result(i) := result(i-1) || K(i).

221# 5. Return: KO := the leftmost L bits of result(n).

222 h = 256

223 r = 32

224

225 n = L // h

226

227 if n == 0: 227 ↛ 230line 227 didn't jump to line 230, because the condition on line 227 was never false

228 n = 1

229

230 if n > (pow(2,r)-1): 230 ↛ 231line 230 didn't jump to line 231, because the condition on line 230 was never true

231 raise Exception("Error computing KDF_CounterMode")

232

233 result = b''

234 K = b''

235

236 for i in range(1,n+1):

237 input = pack('>L', i) + Label + b'\x00' + Context + pack('>L',L)

238 K = hmac.new(KI, input, hashlib.sha256).digest()

239 result = result + K

240

241 return result[:(L//8)]

242

243# [MS-LSAD] Section 5.1.2 / 5.1.3

244 class LSA_SECRET_XP(Structure):

245 structure = (

246 ('Length','<L=0'),

247 ('Version','<L=0'),

248 ('_Secret','_-Secret', 'self["Length"]'),

249 ('Secret', ':'),

250 )

251

252

253 def transformKey(InputKey):

254 # Section 5.1.3

255 OutputKey = []

256 OutputKey.append( chr(ord(InputKey[0:1]) >> 0x01) )

257 OutputKey.append( chr(((ord(InputKey[0:1])&0x01)<<6) | (ord(InputKey[1:2])>>2)) )

258 OutputKey.append( chr(((ord(InputKey[1:2])&0x03)<<5) | (ord(InputKey[2:3])>>3)) )

259 OutputKey.append( chr(((ord(InputKey[2:3])&0x07)<<4) | (ord(InputKey[3:4])>>4)) )

260 OutputKey.append( chr(((ord(InputKey[3:4])&0x0F)<<3) | (ord(InputKey[4:5])>>5)) )

261 OutputKey.append( chr(((ord(InputKey[4:5])&0x1F)<<2) | (ord(InputKey[5:6])>>6)) )

262 OutputKey.append( chr(((ord(InputKey[5:6])&0x3F)<<1) | (ord(InputKey[6:7])>>7)) )

263 OutputKey.append( chr(ord(InputKey[6:7]) & 0x7F) )

264

265 for i in range(8):

266 OutputKey[i] = chr((ord(OutputKey[i]) << 1) & 0xfe)

267

268 return b("".join(OutputKey))

269

270 def decryptSecret(key, value):

271 # [MS-LSAD] Section 5.1.2

272 plainText = b''

273 key0 = key

274 for i in range(0, len(value), 8):

275 cipherText = value[:8]

276 tmpStrKey = key0[:7]

277 tmpKey = transformKey(tmpStrKey)

278 Crypt1 = DES.new(tmpKey, DES.MODE_ECB)

279 plainText += Crypt1.decrypt(cipherText)

280 key0 = key0[7:]

281 value = value[8:]

282 # AdvanceKey

283 if len(key0) < 7:

284 key0 = key[len(key0):]

285

286 secret = LSA_SECRET_XP(plainText)

287 return (secret['Secret'])

288

289 def encryptSecret(key, value):

290 # [MS-LSAD] Section 5.1.2

291 cipherText = b''

292 key0 = key

293 value0 = pack('<LL', len(value), 1) + value

294 for i in range(0, len(value0), 8):

295 if len(value0) < 8:

296 value0 = value0 + b'\x00'*(8-len(value0))

297 plainText = value0[:8]

298 tmpStrKey = key0[:7]

299 print(type(tmpStrKey))

300 print(tmpStrKey)

301 tmpKey = transformKey(tmpStrKey)

302 Crypt1 = DES.new(tmpKey, DES.MODE_ECB)

303 cipherText += Crypt1.encrypt(plainText)

304 key0 = key0[7:]

305 value0 = value0[8:]

306 # AdvanceKey

307 if len(key0) < 7:

308 key0 = key[len(key0):]

309

310 return cipherText

311

312 def SamDecryptNTLMHash(encryptedHash, key):

313 # [MS-SAMR] Section 2.2.11.1.1

314 Block1 = encryptedHash[:8]

315 Block2 = encryptedHash[8:]

316

317 Key1 = key[:7]

318 Key1 = transformKey(Key1)

319 Key2 = key[7:14]

320 Key2 = transformKey(Key2)

321

322 Crypt1 = DES.new(Key1, DES.MODE_ECB)

323 Crypt2 = DES.new(Key2, DES.MODE_ECB)

324

325 plain1 = Crypt1.decrypt(Block1)

326 plain2 = Crypt2.decrypt(Block2)

327

328 return plain1 + plain2

329

330 def SamEncryptNTLMHash(encryptedHash, key):

331 # [MS-SAMR] Section 2.2.11.1.1

332 Block1 = encryptedHash[:8]

333 Block2 = encryptedHash[8:]

334

335 Key1 = key[:7]

336 Key1 = transformKey(Key1)

337 Key2 = key[7:14]

338 Key2 = transformKey(Key2)

339

340 Crypt1 = DES.new(Key1, DES.MODE_ECB)

341 Crypt2 = DES.new(Key2, DES.MODE_ECB)

342

343 plain1 = Crypt1.encrypt(Block1)

344 plain2 = Crypt2.encrypt(Block2)

345

346 return plain1 + plain2