Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions api/next/77626.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
pkg crypto, const MLDSAMu = 20 #77626
pkg crypto, const MLDSAMu Hash #77626
pkg crypto/mldsa, const MLDSA44PublicKeySize = 1312 #77626
pkg crypto/mldsa, const MLDSA44PublicKeySize ideal-int #77626
pkg crypto/mldsa, const MLDSA44SignatureSize = 2420 #77626
pkg crypto/mldsa, const MLDSA44SignatureSize ideal-int #77626
pkg crypto/mldsa, const MLDSA65PublicKeySize = 1952 #77626
pkg crypto/mldsa, const MLDSA65PublicKeySize ideal-int #77626
pkg crypto/mldsa, const MLDSA65SignatureSize = 3309 #77626
pkg crypto/mldsa, const MLDSA65SignatureSize ideal-int #77626
pkg crypto/mldsa, const MLDSA87PublicKeySize = 2592 #77626
pkg crypto/mldsa, const MLDSA87PublicKeySize ideal-int #77626
pkg crypto/mldsa, const MLDSA87SignatureSize = 4627 #77626
pkg crypto/mldsa, const MLDSA87SignatureSize ideal-int #77626
pkg crypto/mldsa, const PrivateKeySize = 32 #77626
pkg crypto/mldsa, const PrivateKeySize ideal-int #77626
pkg crypto/mldsa, func GenerateKey(Parameters) (*PrivateKey, error) #77626
pkg crypto/mldsa, func MLDSA44() Parameters #77626
pkg crypto/mldsa, func MLDSA65() Parameters #77626
pkg crypto/mldsa, func MLDSA87() Parameters #77626
pkg crypto/mldsa, func NewPrivateKey(Parameters, []uint8) (*PrivateKey, error) #77626
pkg crypto/mldsa, func NewPublicKey(Parameters, []uint8) (*PublicKey, error) #77626
pkg crypto/mldsa, func Verify(*PublicKey, []uint8, []uint8, *Options) error #77626
pkg crypto/mldsa, method (*Options) HashFunc() crypto.Hash #77626
pkg crypto/mldsa, method (*PrivateKey) Bytes() []uint8 #77626
pkg crypto/mldsa, method (*PrivateKey) Equal(crypto.PrivateKey) bool #77626
pkg crypto/mldsa, method (*PrivateKey) Public() crypto.PublicKey #77626
pkg crypto/mldsa, method (*PrivateKey) PublicKey() *PublicKey #77626
pkg crypto/mldsa, method (*PrivateKey) Sign(io.Reader, []uint8, crypto.SignerOpts) ([]uint8, error) #77626
pkg crypto/mldsa, method (*PrivateKey) SignDeterministic([]uint8, crypto.SignerOpts) ([]uint8, error) #77626
pkg crypto/mldsa, method (*PublicKey) Bytes() []uint8 #77626
pkg crypto/mldsa, method (*PublicKey) Equal(crypto.PublicKey) bool #77626
pkg crypto/mldsa, method (*PublicKey) Parameters() Parameters #77626
pkg crypto/mldsa, method (Parameters) PublicKeySize() int #77626
pkg crypto/mldsa, method (Parameters) SignatureSize() int #77626
pkg crypto/mldsa, method (Parameters) String() string #77626
pkg crypto/mldsa, type Options struct #77626
pkg crypto/mldsa, type Options struct, Context string #77626
pkg crypto/mldsa, type Parameters struct #77626
pkg crypto/mldsa, type PrivateKey struct #77626
pkg crypto/mldsa, type PublicKey struct #77626
6 changes: 6 additions & 0 deletions doc/next/6-stdlib/70-mldsa.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
### crypto/mldsa

<!-- https://go.dev/issue/77626 --->

The new [crypto/mldsa] package implements the post-quantum ML-DSA signature
scheme specified in FIPS 204.
2 changes: 2 additions & 0 deletions doc/next/6-stdlib/99-minor/crypto/77626.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
The new [MLDSAMu] [Hash] value is meant to be used as a signaling mechanism for
External μ ML-DSA signing.
1 change: 1 addition & 0 deletions doc/next/6-stdlib/99-minor/crypto/mldsa/77626.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<!-- crypto/mldsa is documented in doc/next/6-stdlib/70-mldsa.md. -->
3 changes: 3 additions & 0 deletions doc/next/6-stdlib/99-minor/crypto/x509/75260.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
When parsing into [pkix.Name] fields, a wider range of
[pkix.AttributeTypeAndValue.Value] types is now supported, and unknown types are
parsed into [asn1.RawValue].
9 changes: 9 additions & 0 deletions src/cmd/asm/internal/asm/testdata/amd64enc.s
Original file line number Diff line number Diff line change
Expand Up @@ -2425,6 +2425,15 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
MOVQ $-249346713, (R11) // 49c703674523f1
MOVQ $-249346713, DX // 48c7c2674523f1
MOVQ $-249346713, R11 // 49c7c3674523f1
// Positive immediates that fit in 32 bits use the shorter 5-byte
// MOV r64, imm32 (zero-extended) form rather than the 7-byte sign-
// extended c7 /0 form. See Ziq_rp in cmd/internal/obj/x86/asm6.go.
MOVQ $305419896, DX // ba78563412
MOVQ $305419896, R11 // 41bb78563412
MOVQ $2147483648, DX // ba00000080
MOVQ $2147483648, R11 // 41bb00000080
MOVQ $4294967295, DX // baffffffff
MOVQ $4294967295, R11 // 41bbffffffff
MOVQ DX, (BX) // 488913
MOVQ R11, (BX) // 4c891b
MOVQ DX, (R11) // 498913
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/compile/internal/ssa/debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -1056,7 +1056,7 @@ func (state *debugState) processValue(v *Value, vSlots []SlotID, vReg *Register)
if clobbers.empty() {
break
}
reg := pickReg(clobbers)
reg := clobbers.pickReg()
clobbers = clobbers.removeReg(reg)

for _, slot := range locs.registers[reg] {
Expand Down
61 changes: 36 additions & 25 deletions src/cmd/compile/internal/ssa/regalloc.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,17 @@ func (r regMask) empty() bool {
return r.v1 == 0 && r.v2 == 0
}

func (r regMask) pickReg() register {
if r.empty() {
panic("can't pick a register from an empty set")
}
// pick the lowest one
if r.v1 != 0 {
return register(bits.TrailingZeros64(r.v1))
}
return register(bits.TrailingZeros64(r.v2) + 64)
}

func regMaskAt(i register) regMask {
if i < 64 {
return regMask{v1: 1 << i}
Expand Down Expand Up @@ -248,16 +259,16 @@ func countRegs(r regMask) int {
return bits.OnesCount64(r.v1) + bits.OnesCount64(r.v2)
}

// pickReg picks an arbitrary register from the register mask.
func pickReg(r regMask) register {
if r.empty() {
panic("can't pick a register from an empty set")
}
// pick the lowest one
if r.v1 != 0 {
return register(bits.TrailingZeros64(r.v1))
// pickReg picks a register from the register mask.
func (s *regAllocState) pickReg(rm regMask) register {
if s.f.Config.ctxt.Arch.Arch == sys.ArchRISCV64 {
// Prefer x8-x15 and f8-f15 to enable increased use of compressed instructions.
riscv64CompressedMask := rm.intersect(regMask{v1: 0x0000ff000000ff00})
if !riscv64CompressedMask.empty() {
rm = riscv64CompressedMask
}
}
return register(bits.TrailingZeros64(r.v2) + 64)
return rm.pickReg()
}

type use struct {
Expand Down Expand Up @@ -420,15 +431,15 @@ func (s *regAllocState) freeReg(r register) {
// freeRegs frees up all registers listed in m.
func (s *regAllocState) freeRegs(m regMask) {
for !m.intersect(s.used).empty() {
s.freeReg(pickReg(m.intersect(s.used)))
s.freeReg(s.pickReg(m.intersect(s.used)))
}
}

// clobberRegs inserts instructions that clobber registers listed in m.
func (s *regAllocState) clobberRegs(m regMask) {
m = m.intersect(s.allocatable.intersect(s.f.Config.gpRegMask)) // only integer register can contain pointers, only clobber them
for !m.empty() {
r := pickReg(m)
r := s.pickReg(m)
m = m.removeReg(r)
x := s.curBlock.NewValue0(src.NoXPos, OpClobberReg, types.TypeVoid)
s.f.setHome(x, &s.registers[r])
Expand Down Expand Up @@ -490,7 +501,7 @@ func (s *regAllocState) allocReg(mask regMask, v *Value) register {

// Pick an unused register if one is available.
if !mask.minus(s.used).empty() {
r := pickReg(mask.minus(s.used))
r := s.pickReg(mask.minus(s.used))
s.usedSinceBlockStart = s.usedSinceBlockStart.addReg(r)
return r
}
Expand Down Expand Up @@ -537,7 +548,7 @@ func (s *regAllocState) allocReg(mask regMask, v *Value) register {
m := s.compatRegs(v2.Type).minus(s.used).minus(s.tmpused).removeReg(r)
if !m.empty() && !s.values[v2.ID].rematerializeable && countRegs(s.values[v2.ID].regs) == 1 {
s.usedSinceBlockStart = s.usedSinceBlockStart.addReg(r)
r2 := pickReg(m)
r2 := s.pickReg(m)
c := s.curBlock.NewValue1(v2.Pos, OpCopy, v2.Type, s.regs[r].c)
s.copies[c] = false
if s.f.pass.debug > regDebug {
Expand Down Expand Up @@ -608,7 +619,7 @@ func (s *regAllocState) allocValToReg(v *Value, mask regMask, nospill bool, pos
// Check if v is already in a requested register.
if !mask.intersect(vi.regs).empty() {
mask = mask.intersect(vi.regs)
r := pickReg(mask)
r := s.pickReg(mask)
if mask.hasReg(s.SPReg) {
// Prefer the stack pointer if it is allowed.
// (Needed because the op might have an Aux symbol
Expand Down Expand Up @@ -645,7 +656,7 @@ func (s *regAllocState) allocValToReg(v *Value, mask regMask, nospill bool, pos
// v is in a fixed register, prefer that
current = v
} else {
r2 := pickReg(vi.regs)
r2 := s.pickReg(vi.regs)
if s.regs[r2].v != v {
panic("bad register state")
}
Expand Down Expand Up @@ -1251,7 +1262,7 @@ func (s *regAllocState) regalloc(f *Func) {
// They're not suitable for further (phi-function) allocation.
m := s.values[a.ID].regs.minus(phiUsed).intersect(s.allocatable)
if !m.empty() {
r := pickReg(m)
r := s.pickReg(m)
phiUsed = phiUsed.addReg(r)
phiRegs = append(phiRegs, r)
} else {
Expand Down Expand Up @@ -1280,7 +1291,7 @@ func (s *regAllocState) regalloc(f *Func) {
// them (and they are not going to be helpful anyway).
m := s.compatRegs(a.Type).minus(s.used).minus(phiUsed)
if !m.empty() && !s.values[a.ID].rematerializeable && countRegs(s.values[a.ID].regs) == 1 {
r2 := pickReg(m)
r2 := s.pickReg(m)
c := p.NewValue1(a.Pos, OpCopy, a.Type, s.regs[r].c)
s.copies[c] = false
if s.f.pass.debug > regDebug {
Expand Down Expand Up @@ -1326,7 +1337,7 @@ func (s *regAllocState) regalloc(f *Func) {
}
}
if !m.empty() {
r := pickReg(m)
r := s.pickReg(m)
phiRegs[i] = r
phiUsed = phiUsed.addReg(r)
}
Expand Down Expand Up @@ -1458,7 +1469,7 @@ func (s *regAllocState) regalloc(f *Func) {
continue
}
desired.clobber(j.regs)
desired.add(v.Args[j.idx].ID, pickReg(j.regs))
desired.add(v.Args[j.idx].ID, s.pickReg(j.regs))
}
if opcodeTable[v.Op].resultInArg0 || v.Op == OpAMD64ADDQconst || v.Op == OpAMD64ADDLconst || v.Op == OpSelect0 {
if opcodeTable[v.Op].commutative {
Expand Down Expand Up @@ -1508,7 +1519,7 @@ func (s *regAllocState) regalloc(f *Func) {
if countRegs(m) != 1 {
f.Fatalf("bad fixed-register op %s", v)
}
s.assignReg(pickReg(m), v, v)
s.assignReg(s.pickReg(m), v, v)
default:
f.Fatalf("unknown fixed-register op %s", v)
}
Expand Down Expand Up @@ -2848,19 +2859,19 @@ func (e *edgeState) findRegFor(typ *types.Type) Location {
// 4) a register holding a rematerializeable value
x := m.minus(e.usedRegs)
if !x.empty() {
return &e.s.registers[pickReg(x)]
return &e.s.registers[e.s.pickReg(x)]
}
x = m.minus(e.uniqueRegs).minus(e.finalRegs)
if !x.empty() {
return &e.s.registers[pickReg(x)]
return &e.s.registers[e.s.pickReg(x)]
}
x = m.minus(e.uniqueRegs)
if !x.empty() {
return &e.s.registers[pickReg(x)]
return &e.s.registers[e.s.pickReg(x)]
}
x = m.intersect(e.rematerializeableRegs)
if !x.empty() {
return &e.s.registers[pickReg(x)]
return &e.s.registers[e.s.pickReg(x)]
}

// No register is available.
Expand Down Expand Up @@ -3281,7 +3292,7 @@ func (s *regAllocState) computeDesired() {
continue
}
desired.clobber(j.regs)
desired.add(v.Args[j.idx].ID, pickReg(j.regs))
desired.add(v.Args[j.idx].ID, s.pickReg(j.regs))
}
// Set desired register of input 0 if this is a 2-operand instruction.
if opcodeTable[v.Op].resultInArg0 || v.Op == OpAMD64ADDQconst || v.Op == OpAMD64ADDLconst || v.Op == OpSelect0 {
Expand Down
7 changes: 4 additions & 3 deletions src/cmd/compile/internal/types2/stdlib_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,9 +355,10 @@ func TestStdKen(t *testing.T) {
var excluded = map[string]bool{
"builtin": true,
"cmd/compile/internal/ssa/_gen": true,
"runtime/_mkmalloc": true,
"simd/archsimd/_gen/simdgen": true,
"simd/archsimd/_gen/unify": true,
"crypto/internal/cryptotest/wycheproof/_schema": true,
"runtime/_mkmalloc": true,
"simd/archsimd/_gen/simdgen": true,
"simd/archsimd/_gen/unify": true,
}

// printPackageMu synchronizes the printing of type-checked package files in
Expand Down
4 changes: 2 additions & 2 deletions src/cmd/compile/internal/walk/expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -1015,7 +1015,7 @@ func walkStringHeader(n *ir.StringHeaderExpr, init *ir.Nodes) ir.Node {
return n
}

// return 1 if integer n must be in range [0, max), 0 otherwise.
// bounded reports whether integer n must be in range [0, max).
func bounded(n ir.Node, max int64) bool {
if n.Type() == nil || !n.Type().IsInteger() {
return false
Expand Down Expand Up @@ -1073,7 +1073,7 @@ func bounded(n ir.Node, max int64) bool {
if !sign && ir.IsSmallIntConst(n.Y) {
v := ir.Int64Val(n.Y)
if v > int64(bits) {
return true
return max > 0
}
bits -= int32(v)
}
Expand Down
5 changes: 2 additions & 3 deletions src/cmd/internal/obj/x86/asm6.go
Original file line number Diff line number Diff line change
Expand Up @@ -484,8 +484,7 @@ var ymovq = []ytab{
// valid only in 64-bit mode, usually with 64-bit prefix
{Zr_m, 1, argList{Yrl, Yml}}, // 0x89
{Zm_r, 1, argList{Yml, Yrl}}, // 0x8b
{Zilo_m, 2, argList{Ys32, Yrl}}, // 32 bit signed 0xc7,(0)
{Ziq_rp, 1, argList{Yi64, Yrl}}, // 0xb8 -- 32/64 bit immediate
{Ziq_rp, 1, argList{Yi64, Yrl}}, // 0xb8 -- 32/64 bit immediate (Ziq_rp picks 5/7/10-byte form)
{Zilo_m, 2, argList{Yi32, Yml}}, // 0xc7,(0)
{Zm_r_xm, 1, argList{Ymm, Ymr}}, // 0x6e MMX MOVD
{Zr_m_xm, 1, argList{Ymr, Ymm}}, // 0x7e MMX MOVD
Expand Down Expand Up @@ -1225,7 +1224,7 @@ var optab =
{AMOVNTPD, yxr_ml, Pe, opBytes{0x2b}},
{AMOVNTPS, yxr_ml, Pm, opBytes{0x2b}},
{AMOVNTQ, ymr_ml, Pm, opBytes{0xe7}},
{AMOVQ, ymovq, Pw8, opBytes{0x6f, 0x7f, Pf2, 0xd6, Pf3, 0x7e, Pe, 0xd6, 0x89, 0x8b, 0xc7, 00, 0xb8, 0xc7, 00, 0x6e, 0x7e, Pe, 0x6e, Pe, 0x7e, 0}},
{AMOVQ, ymovq, Pw8, opBytes{0x6f, 0x7f, Pf2, 0xd6, Pf3, 0x7e, Pe, 0xd6, 0x89, 0x8b, 0xb8, 0xc7, 00, 0x6e, 0x7e, Pe, 0x6e, Pe, 0x7e, 0}},
{AMOVQOZX, ymrxr, Pf3, opBytes{0xd6, 0x7e}},
{AMOVSB, ynone, Pb, opBytes{0xa4}},
{AMOVSD, yxmov, Pf2, opBytes{0x10, 0x11}},
Expand Down
67 changes: 67 additions & 0 deletions src/crypto/cipher/cbc_aes_wycheproof_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright 2026 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package cipher_test

import (
"crypto/aes"
"crypto/cipher"
"crypto/internal/cryptotest"
"crypto/internal/cryptotest/wycheproof"
"encoding/hex"
"testing"
)

func TestCBCAESWycheproof(t *testing.T) {
cryptotest.TestAllImplementations(t, "aes", func(t *testing.T) {
file := "aes_cbc_pkcs5_test.json"
var testdata wycheproof.IndCpaTestSchemaV1Json
wycheproof.LoadVectorFile(t, file, &testdata)

for _, tg := range testdata.TestGroups {
for _, tv := range tg.Tests {
t.Run(wycheproof.TestName(file, tv), func(t *testing.T) {
t.Parallel()

block, err := aes.NewCipher(wycheproof.MustDecodeHex(tv.Key))
if err != nil {
t.Fatalf("NewCipher: %v", err)
}
mode := cipher.NewCBCDecrypter(block, wycheproof.MustDecodeHex(tv.Iv))
ct := wycheproof.MustDecodeHex(tv.Ct)
if len(ct)%aes.BlockSize != 0 {
t.Fatalf("ciphertext is not a multiple of the block size")
}
mode.CryptBlocks(ct, ct) // decrypt the block in place

// Test cases with bad/missing padding are expected to fail,
// but cipher.CBCDecrypter doesn't validate padding. Skip these.
// Fail loudly if there's an invalid test for any other reason,
// so we can evaluate what to do with it.
for _, flag := range tv.Flags {
if flag == "BadPadding" || flag == "NoPadding" {
return
}
}
if !wycheproof.ShouldPass(t, tv.Result, tv.Flags, nil) {
t.Fatalf("unexpected invalid test (not BadPadding/NoPadding)")
}

// Remove the PKCS#5 padding from the given ciphertext to validate it
padding := ct[len(ct)-1]
paddingNum := int(padding)
for i := paddingNum; i > 0; i-- {
if ct[len(ct)-i] != padding { // panic if the padding is unexpectedly bad
t.Fatalf("bad padding at index=%d of %v", i, ct)
}
}
ct = ct[:len(ct)-paddingNum]

if got, want := hex.EncodeToString(ct), tv.Msg; got != want {
t.Errorf("decoded ciphertext not equal: %s, want %s", got, want)
}
})
}
}
})
}
Loading
Loading