You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
DateKeys/capsule/padding.go

73 lines
2.3 KiB

package capsule
import (
"fmt"
"math/bits"
)
// Padding is the padding rule of the payload of a format 2 capsule, sealed in
// key 7 of CONTROL_CBOR (spec §29.1, §31). No code stands for no padding.
type Padding uint8
// Padding rules of format 2 (spec §29.1).
const (
// Bloque256 pads the content to the next multiple of 256 bytes, and to
// at least 256.
Bloque256 Padding = 1
// Reforzado pads to the larger of Bloque256 and Padmé. It is the rule
// Encrypt uses by default, as spec §29.1 asks of the official SDK.
Reforzado Padding = 2
)
// MaxPayloadLength is L_MAX = 2^53 - 2^46, the largest content length a
// format 2 capsule can seal: the largest L for which both rules give a P of
// at most 2^53 - 1 (spec §29.1).
const MaxPayloadLength = 1<<53 - 1<<46
func (p Padding) String() string {
switch p {
case Bloque256:
return "bloque256"
case Reforzado:
return "reforzado"
}
return fmt.Sprintf("padding(%d)", uint8(p))
}
func (p Padding) valid() bool { return p == Bloque256 || p == Reforzado }
// PaddedLength returns P = rule(L), the exact length of the plaintext of
// PAYLOAD_AGE in a format 2 capsule whose content is l bytes long (spec
// §29.1). The arithmetic is exact and on 64-bit integers only, never a
// floating-point logarithm or 32-bit operations.
func PaddedLength(l uint64, p Padding) (uint64, error) {
if !p.valid() {
return 0, fmt.Errorf("capsule: padding code %d is not defined", uint8(p))
}
if l > MaxPayloadLength {
return 0, fmt.Errorf("capsule: content of %d bytes exceeds L_MAX = %d", l, uint64(MaxPayloadLength))
}
if l <= 256 {
return 256, nil
}
block := (l + 255) &^ 255
if p == Bloque256 {
return block, nil
}
// Padmé: keep the S + 1 most significant bits of L and round up the
// others, with E = floor(log2 L) and S = floor(log2 E) + 1.
e := uint64(bits.Len64(l) - 1)
s := uint64(bits.Len64(e))
mask := uint64(1)<<(e-s) - 1
return max(block, (l+mask)&^mask), nil
}
// PayloadAgeLength returns the length of a PAYLOAD_AGE whose plaintext is n
// bytes long: the 184 bytes of an age header with one X25519 stanza and the
// nonce, the plaintext, and the 16-byte tag of each 64 KiB STREAM chunk, at
// least one (spec §62.1, informative note).
func PayloadAgeLength(n uint64) uint64 {
chunks := max(1, (n+65535)/65536)
return 184 + n + 16*chunks
}

Powered by TurnKey Linux.