1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
|
package ipmi
import "context"
// 22.15.2 Cipher Suite IDs
type CipherSuiteID uint8
const (
CipherSuiteID0 CipherSuiteID = 0
CipherSuiteID1 CipherSuiteID = 1
CipherSuiteID2 CipherSuiteID = 2
CipherSuiteID3 CipherSuiteID = 3
CipherSuiteID4 CipherSuiteID = 4
CipherSuiteID5 CipherSuiteID = 5
CipherSuiteID6 CipherSuiteID = 6
CipherSuiteID7 CipherSuiteID = 7
CipherSuiteID8 CipherSuiteID = 8
CipherSuiteID9 CipherSuiteID = 9
CipherSuiteID10 CipherSuiteID = 10
CipherSuiteID11 CipherSuiteID = 11
CipherSuiteID12 CipherSuiteID = 12
CipherSuiteID13 CipherSuiteID = 13
CipherSuiteID14 CipherSuiteID = 14
CipherSuiteID15 CipherSuiteID = 15
CipherSuiteID16 CipherSuiteID = 16
CipherSuiteID17 CipherSuiteID = 17
CipherSuiteID18 CipherSuiteID = 18
CipherSuiteID19 CipherSuiteID = 19
CipherSuiteIDReserved CipherSuiteID = 0xff
)
const (
StandardCipherSuite uint8 = 0xc0
OEMCipherSuite uint8 = 0xc1
CipherAlgMask uint8 = 0x3f // [5:0]=111111b
CipherAlgTagBitMask uint8 = 0xc0 // [7:6]=11b
CipherAlgTagBitAuthMask uint8 = 0x00 // [7:6]=00b
CipherAlgTagBitIntegrityMask uint8 = 0x40 // [7:6]=01b
CipherAlgTagBitEncryptionMask uint8 = 0x80 // [7:6]=10b
LIST_ALGORITHMS_BY_CIPHER_SUITE uint8 = 0x80
)
// getCipherSuiteAlgorithms returns AuthAlg, IntegrityAlg and CryptAlg of the specified cipherSuiteID.
func getCipherSuiteAlgorithms(cipherSuiteID CipherSuiteID) (authAlg AuthAlg, integrity IntegrityAlg, encryptionAlg CryptAlg, err error) {
switch cipherSuiteID {
case CipherSuiteID0:
return AuthAlgRAKP_None, IntegrityAlg_None, CryptAlg_None, nil
case CipherSuiteID1:
return AuthAlgRAKP_HMAC_SHA1, IntegrityAlg_None, CryptAlg_None, nil
case CipherSuiteID2:
return AuthAlgRAKP_HMAC_SHA1, IntegrityAlg_HMAC_SHA1_96, CryptAlg_None, nil
case CipherSuiteID3:
return AuthAlgRAKP_HMAC_SHA1, IntegrityAlg_HMAC_SHA1_96, CryptAlg_AES_CBC_128, nil
case CipherSuiteID4:
return AuthAlgRAKP_HMAC_SHA1, IntegrityAlg_HMAC_SHA1_96, CryptAlg_xRC4_128, nil
case CipherSuiteID5:
return AuthAlgRAKP_HMAC_SHA1, IntegrityAlg_HMAC_SHA1_96, CryptAlg_xRC4_40, nil
case CipherSuiteID6:
return AuthAlgRAKP_HMAC_MD5, IntegrityAlg_None, CryptAlg_None, nil
case CipherSuiteID7:
return AuthAlgRAKP_HMAC_MD5, IntegrityAlg_HMAC_MD5_128, CryptAlg_None, nil
case CipherSuiteID8:
return AuthAlgRAKP_HMAC_MD5, IntegrityAlg_HMAC_MD5_128, CryptAlg_AES_CBC_128, nil
case CipherSuiteID9:
return AuthAlgRAKP_HMAC_MD5, IntegrityAlg_HMAC_MD5_128, CryptAlg_xRC4_128, nil
case CipherSuiteID10:
return AuthAlgRAKP_HMAC_MD5, IntegrityAlg_HMAC_MD5_128, CryptAlg_xRC4_40, nil
case CipherSuiteID11:
return AuthAlgRAKP_HMAC_MD5, IntegrityAlg_MD5_128, CryptAlg_None, nil
case CipherSuiteID12:
return AuthAlgRAKP_HMAC_MD5, IntegrityAlg_MD5_128, CryptAlg_AES_CBC_128, nil
case CipherSuiteID13:
return AuthAlgRAKP_HMAC_MD5, IntegrityAlg_MD5_128, CryptAlg_xRC4_128, nil
case CipherSuiteID14:
return AuthAlgRAKP_HMAC_MD5, IntegrityAlg_MD5_128, CryptAlg_xRC4_40, nil
case CipherSuiteID15:
return AuthAlgRAKP_HMAC_SHA256, IntegrityAlg_None, CryptAlg_None, nil
case CipherSuiteID16:
return AuthAlgRAKP_HMAC_SHA256, IntegrityAlg_HMAC_SHA256_128, CryptAlg_None, nil
case CipherSuiteID17:
return AuthAlgRAKP_HMAC_SHA256, IntegrityAlg_HMAC_SHA256_128, CryptAlg_AES_CBC_128, nil
case CipherSuiteID18:
return AuthAlgRAKP_HMAC_SHA256, IntegrityAlg_HMAC_SHA256_128, CryptAlg_xRC4_128, nil
case CipherSuiteID19:
return AuthAlgRAKP_HMAC_SHA256, IntegrityAlg_HMAC_SHA256_128, CryptAlg_xRC4_40, nil
case CipherSuiteIDReserved:
return 0, 0, 0, nil
default:
return 0, 0, 0, nil
}
}
// 22.15.1 Cipher Suite Records
// The size of a CipherSuiteRecord is
type CipherSuiteRecord struct {
// If StartOfRecord is C0h, indicating that the Start Of Record byte is followed by an Cipher Suite ID
// If StartOfRecord is C1h, indicating that the Start Of Record byte is followed by a OEM Cipher Suite ID plus OEM IANA
StartOfRecord uint8
// a numeric way of identifying the Cipher Suite on the platform
CipherSuitID CipherSuiteID
OEMIanaID uint32 // Least significant byte first. 3-byte IANA for the OEM or body that defined the Cipher Suite.
// an authentication algorithm number is required for all Cipher Suites.
// It is possible that a given Cipher Suite may not specify use of an integrity or confidentiality algorithm.
AuthAlg uint8 // Tag bits: [7:6]=00b
IntegrityAlgs []uint8 // Tag bits: [7:6]=01b
CryptAlgs []uint8 // Tag bits: [7:6]=10b
}
func (c *Client) findBestCipherSuites(ctx context.Context) []CipherSuiteID {
cipherSuiteRecords, err := c.GetAllChannelCipherSuites(ctx, ChannelNumberSelf)
if err != nil {
return preferredCiphers
}
cipherSuiteIDs := make([]CipherSuiteID, len(cipherSuiteRecords))
for i, cipherSuiteRecord := range cipherSuiteRecords {
cipherSuiteIDs[i] = cipherSuiteRecord.CipherSuitID
}
return sortCipherSuites(cipherSuiteIDs)
}
// sortCipherSuites return cipher suites in order of preference.
// the cipher suite not in the preferredCiphers list would be excluded.
func sortCipherSuites(cipherSuites []CipherSuiteID) []CipherSuiteID {
sorted := make([]CipherSuiteID, 0)
for _, preferredCipher := range preferredCiphers {
for _, cipherSuiteID := range cipherSuites {
if preferredCipher == cipherSuiteID {
sorted = append(sorted, cipherSuiteID)
}
}
}
return sorted
}
var preferredCiphers = []CipherSuiteID{
// Todo
// cipher suite best order is chosen with this criteria:
// xRC4 is bad
// AES128 is required
// HMAC-SHA256 > HMAC-SHA1
// secure authentication > encrypted content
// With xRC4 out, all cipher suites with MD5 out, and cipher suite 3
// being required by the spec, the only better defined standard cipher
// suite is 17. So if SHA256 is available, we should try to use that,
// otherwise, fall back to 3.
CipherSuiteID17,
// IPMI 2.0 spec requires that cipher suite 3 is implemented
// so we should always be able to fall back to that if better
// options are not available.
// CipherSuiteID3 -> 01h, 01h, 01h
CipherSuiteID3,
CipherSuiteID15,
CipherSuiteID16,
CipherSuiteID18,
CipherSuiteID19,
CipherSuiteID6,
CipherSuiteID7,
CipherSuiteID8,
CipherSuiteID11,
CipherSuiteID12,
// xRC4 is bad, so we don't use it
// CipherSuiteID4,
// CipherSuiteID5,
// CipherSuiteID9,
// CipherSuiteID10,
// CipherSuiteID13,
// CipherSuiteID14,
}
|