extractPadding returns, in constant time, the length of the padding to remove from the end of payload. It also returns a byte which is equal to 255 if the padding was valid and 0 otherwise. See RFC 2246, Section 6.2.3.2.
(payload []byte)
| 286 | // from the end of payload. It also returns a byte which is equal to 255 if the |
| 287 | // padding was valid and 0 otherwise. See RFC 2246, Section 6.2.3.2. |
| 288 | func extractPadding(payload []byte) (toRemove int, good byte) { |
| 289 | if len(payload) < 1 { |
| 290 | return 0, 0 |
| 291 | } |
| 292 | |
| 293 | paddingLen := payload[len(payload)-1] |
| 294 | t := uint(len(payload)-1) - uint(paddingLen) |
| 295 | // if len(payload) >= (paddingLen - 1) then the MSB of t is zero |
| 296 | good = byte(int32(^t) >> 31) |
| 297 | |
| 298 | // The maximum possible padding length plus the actual length field |
| 299 | toCheck := 256 |
| 300 | // The length of the padded data is public, so we can use an if here |
| 301 | if toCheck > len(payload) { |
| 302 | toCheck = len(payload) |
| 303 | } |
| 304 | |
| 305 | for i := 0; i < toCheck; i++ { |
| 306 | t := uint(paddingLen) - uint(i) |
| 307 | // if i <= paddingLen then the MSB of t is zero |
| 308 | mask := byte(int32(^t) >> 31) |
| 309 | b := payload[len(payload)-1-i] |
| 310 | good &^= mask&paddingLen ^ mask&b |
| 311 | } |
| 312 | |
| 313 | // We AND together the bits of good and replicate the result across |
| 314 | // all the bits. |
| 315 | good &= good << 4 |
| 316 | good &= good << 2 |
| 317 | good &= good << 1 |
| 318 | good = uint8(int8(good) >> 7) |
| 319 | |
| 320 | // Zero the padding length on error. This ensures any unchecked bytes |
| 321 | // are included in the MAC. Otherwise, an attacker that could |
| 322 | // distinguish MAC failures from padding failures could mount an attack |
| 323 | // similar to POODLE in SSL 3.0: given a good ciphertext that uses a |
| 324 | // full block's worth of padding, replace the final block with another |
| 325 | // block. If the MAC check passed but the padding check failed, the |
| 326 | // last byte of that block decrypted to the block size. |
| 327 | // |
| 328 | // See also macAndPaddingGood logic below. |
| 329 | paddingLen &= good |
| 330 | |
| 331 | toRemove = int(paddingLen) + 1 |
| 332 | return |
| 333 | } |
| 334 | |
| 335 | func roundUp(a, b int) int { |
| 336 | return a + (b-a%b)%b |
no outgoing calls
no test coverage detected
searching dependent graphs…