blob: 7e0fce1adec8cbac9e5cca2f223637c6d90d4fdf [file] [log] [blame]
Scott Baker2c1c4822019-10-16 11:02:41 -07001package pac
2
3import (
4 "bytes"
5
6 "gopkg.in/jcmturner/gokrb5.v7/iana/chksumtype"
7 "gopkg.in/jcmturner/rpc.v1/mstypes"
8)
9
10/*
11https://msdn.microsoft.com/en-us/library/cc237955.aspx
12
13The Key Usage Value MUST be KERB_NON_KERB_CKSUM_SALT (17) [MS-KILE] (section 3.1.5.9).
14
15Server Signature (SignatureType = 0x00000006)
16https://msdn.microsoft.com/en-us/library/cc237957.aspx
17The KDC will use the long-term key that the KDC shares with the server, so that the server can verify this signature on receiving a PAC.
18The server signature is a keyed hash [RFC4757] of the entire PAC message, with the Signature fields of both PAC_SIGNATURE_DATA structures set to zero.
19The key used to protect the ciphertext part of the response is used.
20The checksum type corresponds to the key unless the key is DES, in which case the KERB_CHECKSUM_HMAC_MD5 key is used.
21The resulting hash value is then placed in the Signature field of the server's PAC_SIGNATURE_DATA structure.
22
23KDC Signature (SignatureType = 0x00000007)
24https://msdn.microsoft.com/en-us/library/dd357117.aspx
25The KDC will use KDC (krbtgt) key [RFC4120], so that other KDCs can verify this signature on receiving a PAC.
26The KDC signature is a keyed hash [RFC4757] of the Server Signature field in the PAC message.
27The cryptographic system that is used to calculate the checksum depends on which system the KDC supports, as defined below:
28- Supports RC4-HMAC --> KERB_CHECKSUM_HMAC_MD5
29- Does not support RC4-HMAC and supports AES256 --> HMAC_SHA1_96_AES256
30- Does not support RC4-HMAC or AES256-CTS-HMAC-SHA1-96, and supports AES128-CTS-HMAC-SHA1-96 --> HMAC_SHA1_96_AES128
31- Does not support RC4-HMAC, AES128-CTS-HMAC-SHA1-96 or AES256-CTS-HMAC-SHA1-96 --> None. The checksum operation will fail.
32*/
33
34// SignatureData implements https://msdn.microsoft.com/en-us/library/cc237955.aspx
35type SignatureData struct {
36 SignatureType uint32 // A 32-bit unsigned integer value in little-endian format that defines the cryptographic system used to calculate the checksum. This MUST be one of the following checksum types: KERB_CHECKSUM_HMAC_MD5 (signature size = 16), HMAC_SHA1_96_AES128 (signature size = 12), HMAC_SHA1_96_AES256 (signature size = 12).
37 Signature []byte // Size depends on the type. See comment above.
38 RODCIdentifier uint16 // A 16-bit unsigned integer value in little-endian format that contains the first 16 bits of the key version number ([MS-KILE] section 3.1.5.8) when the KDC is an RODC. When the KDC is not an RODC, this field does not exist.
39}
40
41// Unmarshal bytes into the SignatureData struct
42func (k *SignatureData) Unmarshal(b []byte) (rb []byte, err error) {
43 r := mstypes.NewReader(bytes.NewReader(b))
44
45 k.SignatureType, err = r.Uint32()
46 if err != nil {
47 return
48 }
49
50 var c int
51 switch k.SignatureType {
52 case chksumtype.KERB_CHECKSUM_HMAC_MD5_UNSIGNED:
53 c = 16
54 case uint32(chksumtype.HMAC_SHA1_96_AES128):
55 c = 12
56 case uint32(chksumtype.HMAC_SHA1_96_AES256):
57 c = 12
58 }
59 k.Signature, err = r.ReadBytes(c)
60 if err != nil {
61 return
62 }
63
64 // When the KDC is not an Read Only Domain Controller (RODC), this field does not exist.
65 if len(b) >= 4+c+2 {
66 k.RODCIdentifier, err = r.Uint16()
67 if err != nil {
68 return
69 }
70 }
71
72 // Create bytes with zeroed signature needed for checksum verification
73 rb = make([]byte, len(b), len(b))
74 copy(rb, b)
75 z := make([]byte, len(b), len(b))
76 copy(rb[4:4+c], z)
77
78 return
79}