Skip to content

Commit aef0fb2

Browse files
committed
Add PKINIT structures for AS-REQ
1 parent 69dffc1 commit aef0fb2

5 files changed

Lines changed: 311 additions & 32 deletions

File tree

scapy/asn1/mib.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,23 @@ def load_mib(filenames):
260260
"1.3.14.3.2.29": "sha1RSASign",
261261
}
262262

263+
# nist #
264+
265+
nist_oids = {
266+
"2.16.840.1.101.3.4.2.1": "sha256",
267+
"2.16.840.1.101.3.4.2.2": "sha384",
268+
"2.16.840.1.101.3.4.2.3": "sha512",
269+
"2.16.840.1.101.3.4.2.4": "sha224",
270+
"2.16.840.1.101.3.4.2.5": "sha512-224",
271+
"2.16.840.1.101.3.4.2.6": "sba512-256",
272+
"2.16.840.1.101.3.4.2.7": "sha3-224",
273+
"2.16.840.1.101.3.4.2.8": "sha3-256",
274+
"2.16.840.1.101.3.4.2.9": "sha3-384",
275+
"2.16.840.1.101.3.4.2.10": "sha3-512",
276+
"2.16.840.1.101.3.4.2.11": "shake128",
277+
"2.16.840.1.101.3.4.2.12": "shake256",
278+
}
279+
263280
# thawte #
264281

265282
thawte_oids = {
@@ -477,6 +494,7 @@ def load_mib(filenames):
477494
"2.5.29.69": "id-ce-holderNameConstraints",
478495
# [MS-WCCE]
479496
"1.3.6.1.4.1.311.2.1.14": "CERT_EXTENSIONS",
497+
"1.3.6.1.4.1.311.10.3.4": "szOID_EFS_CRYPTO",
480498
"1.3.6.1.4.1.311.20.2": "ENROLL_CERTTYPE",
481499
"1.3.6.1.4.1.311.25.1": "NTDS_REPLICATION",
482500
"1.3.6.1.4.1.311.25.2": "NTDS_CA_SECURITY_EXT",
@@ -566,6 +584,12 @@ def load_mib(filenames):
566584
"1.2.840.10045.4.3.4": "ecdsa-with-SHA512"
567585
}
568586

587+
# ansi-x942 #
588+
589+
x942KeyType_oids = {
590+
"1.2.840.10046.2.1": "szOID_ANSI_x942_DH", # RFC3770 sect 4.1.1
591+
}
592+
569593
# elliptic curves #
570594

571595
ansiX962Curve_oids = {
@@ -678,10 +702,27 @@ def load_mib(filenames):
678702
'1.3.6.1.4.1.311.2.2.30': 'NEGOEX - SPNEGO Extended Negotiation Security Mechanism',
679703
}
680704

705+
# kerberos #
706+
707+
kerberos_oids = {
708+
"1.3.6.1.5.2.3.1": "id-pkinit-authData",
709+
"1.3.6.1.5.2.3.2": "id-pkinit-DHKeyData",
710+
"1.3.6.1.5.2.3.3": "id-pkinit-rkeyData",
711+
"1.3.6.1.5.2.3.4": "id-pkinit-KPClientAuth",
712+
"1.3.6.1.5.2.3.5": "id-pkinit-KPKdc",
713+
# RFC8363
714+
"1.3.6.1.5.2.3.6": "id-pkinit-kdf",
715+
"1.3.6.1.5.2.3.6.1": "id-pkinit-kdf-sha1",
716+
"1.3.6.1.5.2.3.6.2": "id-pkinit-kdf-sha256",
717+
"1.3.6.1.5.2.3.6.3": "id-pkinit-kdf-sha512",
718+
"1.3.6.1.5.2.3.6.4": "id-pkinit-kdf-sha384",
719+
}
720+
681721

682722
x509_oids_sets = [
683723
pkcs1_oids,
684724
secsig_oids,
725+
nist_oids,
685726
thawte_oids,
686727
pkcs7_oids,
687728
pkcs9_oids,
@@ -697,9 +738,11 @@ def load_mib(filenames):
697738
evPolicy_oids,
698739
x962KeyType_oids,
699740
x962Signature_oids,
741+
x942KeyType_oids,
700742
ansiX962Curve_oids,
701743
certicomCurve_oids,
702744
gssapi_oids,
745+
kerberos_oids,
703746
]
704747

705748
x509_oids = {}

scapy/asn1fields.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,8 @@ def i2repr(self, pkt, x):
606606
# type: (ASN1_Packet, _I) -> str
607607
if self.holds_packets:
608608
return super(ASN1F_SEQUENCE_OF, self).i2repr(pkt, x) # type: ignore
609+
elif x is None:
610+
return "[]"
609611
else:
610612
return "[%s]" % ", ".join(
611613
self.fld.i2repr(pkt, x) for x in x # type: ignore
@@ -987,3 +989,32 @@ def any2i(self, pkt, x):
987989
if hasattr(x, "add_underlayer"):
988990
x.add_underlayer(pkt)
989991
return super(ASN1F_STRING_PacketField, self).any2i(pkt, x)
992+
993+
994+
class ASN1F_STRING_ENCAPS(ASN1F_STRING_PacketField):
995+
"""
996+
ASN1F_STRING that encapsulates a single ASN1 packet.
997+
"""
998+
999+
def __init__(self,
1000+
name, # type: str
1001+
default, # type: Optional[ASN1_Packet]
1002+
cls, # type: Type[ASN1_Packet]
1003+
context=None, # type: Optional[Any]
1004+
implicit_tag=None, # type: Optional[int]
1005+
explicit_tag=None, # type: Optional[int]
1006+
):
1007+
# type: (...) -> None
1008+
self.cls = cls
1009+
super(ASN1F_STRING_ENCAPS, self).__init__( # type: ignore
1010+
name,
1011+
default and bytes(default),
1012+
context=context,
1013+
implicit_tag=implicit_tag,
1014+
explicit_tag=explicit_tag
1015+
)
1016+
1017+
def m2i(self, pkt, s):
1018+
# type: (ASN1_Packet, bytes) -> Tuple[Optional[ASN1_Packet], bytes]
1019+
val = super(ASN1F_STRING_ENCAPS, self).m2i(pkt, s)
1020+
return self.cls(val[0].val, _underlayer=pkt), val[1]

scapy/layers/kerberos.py

Lines changed: 132 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
- Kerberos Pre-Authentication: RFC6113 (FAST)
1414
- Kerberos Principal Name Canonicalization and Cross-Realm Referrals: RFC6806
1515
- Microsoft Windows 2000 Kerberos Change Password and Set Password Protocols: RFC3244
16+
- PKINIT and its extensions: RFC4556, RFC8070, RFC8636 and [MS-PKCA]
1617
- User to User Kerberos Authentication: draft-ietf-cat-user2user-03
1718
- Public Key Cryptography Based User-to-User Authentication (PKU2U): draft-zhu-pku2u-09
1819
- Initial and Pass Through Authentication Using Kerberos V5 (IAKERB):
@@ -59,6 +60,7 @@
5960
import scapy.asn1.mib # noqa: F401
6061
from scapy.asn1.ber import BER_id_dec, BER_Decoding_Error
6162
from scapy.asn1.asn1 import (
63+
ASN1_OID,
6264
ASN1_BIT_STRING,
6365
ASN1_BOOLEAN,
6466
ASN1_Class,
@@ -80,6 +82,7 @@
8082
ASN1F_SEQUENCE,
8183
ASN1F_SEQUENCE_OF,
8284
ASN1F_STRING,
85+
ASN1F_STRING_ENCAPS,
8386
ASN1F_STRING_PacketField,
8487
ASN1F_enum_INTEGER,
8588
ASN1F_optional,
@@ -142,7 +145,15 @@
142145
from scapy.layers.smb import _NV_VERSION
143146
from scapy.layers.smb2 import STATUS_ERREF
144147
from scapy.layers.tls.cert import Cert, PrivKey
145-
from scapy.layers.x509 import X509_AlgorithmIdentifier
148+
from scapy.layers.x509 import (
149+
_CMS_ENCAPSULATED,
150+
CMS_ContentInfo,
151+
CMS_IssuerAndSerialNumber,
152+
CMS_SignedData,
153+
X509_AlgorithmIdentifier,
154+
X509_DirectoryName,
155+
X509_SubjectPublicKeyInfo,
156+
)
146157

147158
# Redirect exports from RFC3961
148159
try:
@@ -1193,7 +1204,8 @@ class KrbFastResponse(ASN1_Packet):
11931204

11941205
_PADATA_CLASSES[136] = (PA_FX_FAST_REQUEST, PA_FX_FAST_REPLY)
11951206

1196-
# RFC 4556
1207+
1208+
# RFC 4556 - PKINIT
11971209

11981210

11991211
# sect 3.2.1
@@ -1203,21 +1215,36 @@ class ExternalPrincipalIdentifier(ASN1_Packet):
12031215
ASN1_codec = ASN1_Codecs.BER
12041216
ASN1_root = ASN1F_SEQUENCE(
12051217
ASN1F_optional(
1206-
ASN1F_STRING("subjectName", "", implicit_tag=0xA0),
1218+
ASN1F_STRING_ENCAPS(
1219+
"subjectName", None, X509_DirectoryName, implicit_tag=0x80
1220+
),
12071221
),
12081222
ASN1F_optional(
1209-
ASN1F_STRING("issuerAndSerialNumber", "", implicit_tag=0xA1),
1223+
ASN1F_STRING_ENCAPS(
1224+
"issuerAndSerialNumber",
1225+
None,
1226+
CMS_IssuerAndSerialNumber,
1227+
implicit_tag=0x81,
1228+
),
12101229
),
12111230
ASN1F_optional(
1212-
ASN1F_STRING("subjectKeyIdentifier", "", implicit_tag=0xA2),
1231+
ASN1F_STRING("subjectKeyIdentifier", "", implicit_tag=0x82),
12131232
),
12141233
)
12151234

12161235

12171236
class PA_PK_AS_REQ(ASN1_Packet):
12181237
ASN1_codec = ASN1_Codecs.BER
12191238
ASN1_root = ASN1F_SEQUENCE(
1220-
ASN1F_STRING("signedAuthpack", "", implicit_tag=0xA0),
1239+
ASN1F_STRING_ENCAPS(
1240+
"signedAuthpack",
1241+
CMS_ContentInfo(
1242+
contentType=ASN1_OID("id-signedData"),
1243+
content=CMS_SignedData(),
1244+
),
1245+
CMS_ContentInfo,
1246+
implicit_tag=0x80,
1247+
),
12211248
ASN1F_optional(
12221249
ASN1F_SEQUENCE_OF(
12231250
"trustedCertifiers",
@@ -1234,6 +1261,96 @@ class PA_PK_AS_REQ(ASN1_Packet):
12341261

12351262
_PADATA_CLASSES[16] = PA_PK_AS_REQ
12361263

1264+
1265+
# [MS-PKCA] sect 2.2.3
1266+
1267+
1268+
class PAChecksum2(ASN1_Packet):
1269+
ASN1_codec = ASN1_Codecs.BER
1270+
ASN1_root = ASN1F_SEQUENCE(
1271+
ASN1F_STRING("checksum", "", explicit_tag=0xA0),
1272+
ASN1F_PACKET(
1273+
"algorithmIdentifier",
1274+
X509_AlgorithmIdentifier(),
1275+
X509_AlgorithmIdentifier,
1276+
explicit_tag=0xA1,
1277+
),
1278+
)
1279+
1280+
1281+
# still RFC 4556 sect 3.2.1
1282+
1283+
1284+
class PKAuthenticator(ASN1_Packet):
1285+
ASN1_codec = ASN1_Codecs.BER
1286+
ASN1_root = ASN1F_SEQUENCE(
1287+
Microseconds("cusec", 0, explicit_tag=0xA0),
1288+
KerberosTime("ctime", GeneralizedTime(), explicit_tag=0xA1),
1289+
UInt32("nonce", 0, explicit_tag=0xA2),
1290+
ASN1F_optional(
1291+
ASN1F_STRING("paChecksum", "", explicit_tag=0xA3),
1292+
),
1293+
# RFC8070 extension
1294+
ASN1F_optional(
1295+
ASN1F_STRING("freshnessToken", "", explicit_tag=0xA4),
1296+
),
1297+
# [MS-PKCA] sect 2.2.3
1298+
ASN1F_optional(
1299+
ASN1F_PACKET("paChecksum2", None, PAChecksum2, explicit_tag=0xA5),
1300+
),
1301+
)
1302+
1303+
1304+
# RFC8636 sect 6
1305+
1306+
1307+
class KDFAlgorithmId(ASN1_Packet):
1308+
ASN1_codec = ASN1_Codecs.BER
1309+
ASN1_root = ASN1F_SEQUENCE(
1310+
ASN1F_OID("kdfId", "", explicit_tag=0xA0),
1311+
)
1312+
1313+
1314+
# still RFC 4556 sect 3.2.1
1315+
1316+
1317+
class AuthPack(ASN1_Packet):
1318+
ASN1_codec = ASN1_Codecs.BER
1319+
ASN1_root = ASN1F_SEQUENCE(
1320+
ASN1F_PACKET(
1321+
"pkAuthenticator",
1322+
PKAuthenticator(),
1323+
PKAuthenticator,
1324+
explicit_tag=0xA0,
1325+
),
1326+
ASN1F_optional(
1327+
ASN1F_PACKET(
1328+
"clientPublicValue",
1329+
X509_SubjectPublicKeyInfo(),
1330+
X509_SubjectPublicKeyInfo,
1331+
explicit_tag=0xA1,
1332+
),
1333+
),
1334+
ASN1F_optional(
1335+
ASN1F_SEQUENCE_OF(
1336+
"supportedCMSTypes",
1337+
[],
1338+
X509_AlgorithmIdentifier,
1339+
explicit_tag=0xA2,
1340+
),
1341+
),
1342+
ASN1F_optional(
1343+
ASN1F_STRING("clientDCNonce", None, explicit_tag=0xA3),
1344+
),
1345+
# RFC8636 extension
1346+
ASN1F_optional(
1347+
ASN1F_SEQUENCE_OF("supportedKDFs", None, KDFAlgorithmId, explicit_tag=0xA4),
1348+
),
1349+
)
1350+
1351+
1352+
_CMS_ENCAPSULATED["1.3.6.1.5.2.3.1"] = AuthPack
1353+
12371354
# sect 3.2.3
12381355

12391356

@@ -1244,6 +1361,10 @@ class DHRepInfo(ASN1_Packet):
12441361
ASN1F_optional(
12451362
ASN1F_STRING("serverDHNonce", "", explicit_tag=0xA1),
12461363
),
1364+
# RFC8636 extension
1365+
ASN1F_optional(
1366+
ASN1F_PACKET("kdf", None, KDFAlgorithmId, explicit_tag=0xA2),
1367+
),
12471368
)
12481369

12491370

@@ -1993,6 +2114,8 @@ class KRB_ERROR(ASN1_Packet):
19932114
91: "KDC_ERR_MORE_PREAUTH_DATA_REQUIRED",
19942115
92: "KDC_ERR_PREAUTH_BAD_AUTHENTICATION_SET",
19952116
93: "KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS",
2117+
# RFC8636
2118+
100: "KDC_ERR_NO_ACCEPTABLE_KDF",
19962119
},
19972120
explicit_tag=0xA6,
19982121
),
@@ -3174,11 +3297,9 @@ def as_req(self):
31743297
if self.x509:
31753298
# Special PKINIT (RFC4556) factor
31763299
pafactor = PADATA(
3177-
padataType=16, # PA-PK-AS-REQ
3178-
padataValue=PA_PK_AS_REQ(
3179-
3180-
)
3300+
padataType=16, padataValue=PA_PK_AS_REQ() # PA-PK-AS-REQ
31813301
)
3302+
raise NotImplementedError("PKINIT isn't implemented yet !")
31823303
else:
31833304
# Key-based factor
31843305

@@ -3209,7 +3330,7 @@ def as_req(self):
32093330
ts_key,
32103331
PA_ENC_TS_ENC(patimestamp=ASN1_GENERALIZED_TIME(now_time)),
32113332
)
3212-
3333+
32133334
# Insert Pre-Authentication data
32143335
padata.insert(
32153336
0,

0 commit comments

Comments
 (0)