Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
959f8f3db0 | ||
|
|
769bcd6997 | ||
|
|
d0a798f774 | ||
|
|
acbcbef23f | ||
|
|
376eb14006 | ||
|
|
b369b723c8 | ||
|
|
6b853fbea3 |
+1
-1
@@ -92,7 +92,7 @@ func jwsEncodeJSON(claimset interface{}, key crypto.Signer, kid KeyID, nonce, ur
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
phead := base64.RawURLEncoding.EncodeToString([]byte(phJSON))
|
||||
phead := base64.RawURLEncoding.EncodeToString(phJSON)
|
||||
var payload string
|
||||
if val, ok := claimset.(string); ok {
|
||||
payload = val
|
||||
|
||||
+1
-1
@@ -234,7 +234,7 @@ func (b *Builder) AddASN1(tag asn1.Tag, f BuilderContinuation) {
|
||||
// Identifiers with the low five bits set indicate high-tag-number format
|
||||
// (two or more octets), which we don't support.
|
||||
if tag&0x1f == 0x1f {
|
||||
b.err = fmt.Errorf("cryptobyte: high-tag number identifier octects not supported: 0x%x", tag)
|
||||
b.err = fmt.Errorf("cryptobyte: high-tag number identifier octets not supported: 0x%x", tag)
|
||||
return
|
||||
}
|
||||
b.AddUint8(uint8(tag))
|
||||
|
||||
@@ -4,8 +4,8 @@ go 1.23.0
|
||||
|
||||
require (
|
||||
golang.org/x/net v0.21.0 // tagx:ignore
|
||||
golang.org/x/sys v0.31.0
|
||||
golang.org/x/term v0.30.0
|
||||
golang.org/x/sys v0.32.0
|
||||
golang.org/x/term v0.31.0
|
||||
)
|
||||
|
||||
require golang.org/x/text v0.23.0 // indirect
|
||||
require golang.org/x/text v0.24.0 // indirect
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
|
||||
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
|
||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
|
||||
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
|
||||
golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
|
||||
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
|
||||
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build (!amd64 && !ppc64le && !ppc64 && !s390x) || !gc || purego
|
||||
//go:build (!amd64 && !loong64 && !ppc64le && !ppc64 && !s390x) || !gc || purego
|
||||
|
||||
package poly1305
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gc && !purego
|
||||
//go:build gc && !purego && (amd64 || loong64 || ppc64 || ppc64le)
|
||||
|
||||
package poly1305
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
// Copyright 2025 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.
|
||||
|
||||
//go:build gc && !purego
|
||||
|
||||
// func update(state *macState, msg []byte)
|
||||
TEXT ·update(SB), $0-32
|
||||
MOVV state+0(FP), R4
|
||||
MOVV msg_base+8(FP), R5
|
||||
MOVV msg_len+16(FP), R6
|
||||
|
||||
MOVV $0x10, R7
|
||||
|
||||
MOVV (R4), R8 // h0
|
||||
MOVV 8(R4), R9 // h1
|
||||
MOVV 16(R4), R10 // h2
|
||||
MOVV 24(R4), R11 // r0
|
||||
MOVV 32(R4), R12 // r1
|
||||
|
||||
BLT R6, R7, bytes_between_0_and_15
|
||||
|
||||
loop:
|
||||
MOVV (R5), R14 // msg[0:8]
|
||||
MOVV 8(R5), R16 // msg[8:16]
|
||||
ADDV R14, R8, R8 // h0 (x1 + y1 = z1', if z1' < x1 then z1' overflow)
|
||||
ADDV R16, R9, R27
|
||||
SGTU R14, R8, R24 // h0.carry
|
||||
SGTU R9, R27, R28
|
||||
ADDV R27, R24, R9 // h1
|
||||
SGTU R27, R9, R24
|
||||
OR R24, R28, R24 // h1.carry
|
||||
ADDV $0x01, R24, R24
|
||||
ADDV R10, R24, R10 // h2
|
||||
|
||||
ADDV $16, R5, R5 // msg = msg[16:]
|
||||
|
||||
multiply:
|
||||
MULV R8, R11, R14 // h0r0.lo
|
||||
MULHVU R8, R11, R15 // h0r0.hi
|
||||
MULV R9, R11, R13 // h1r0.lo
|
||||
MULHVU R9, R11, R16 // h1r0.hi
|
||||
ADDV R13, R15, R15
|
||||
SGTU R13, R15, R24
|
||||
ADDV R24, R16, R16
|
||||
MULV R10, R11, R25
|
||||
ADDV R16, R25, R25
|
||||
MULV R8, R12, R13 // h0r1.lo
|
||||
MULHVU R8, R12, R16 // h0r1.hi
|
||||
ADDV R13, R15, R15
|
||||
SGTU R13, R15, R24
|
||||
ADDV R24, R16, R16
|
||||
MOVV R16, R8
|
||||
MULV R10, R12, R26 // h2r1
|
||||
MULV R9, R12, R13 // h1r1.lo
|
||||
MULHVU R9, R12, R16 // h1r1.hi
|
||||
ADDV R13, R25, R25
|
||||
ADDV R16, R26, R27
|
||||
SGTU R13, R25, R24
|
||||
ADDV R27, R24, R26
|
||||
ADDV R8, R25, R25
|
||||
SGTU R8, R25, R24
|
||||
ADDV R24, R26, R26
|
||||
AND $3, R25, R10
|
||||
AND $-4, R25, R17
|
||||
ADDV R17, R14, R8
|
||||
ADDV R26, R15, R27
|
||||
SGTU R17, R8, R24
|
||||
SGTU R26, R27, R28
|
||||
ADDV R27, R24, R9
|
||||
SGTU R27, R9, R24
|
||||
OR R24, R28, R24
|
||||
ADDV R24, R10, R10
|
||||
SLLV $62, R26, R27
|
||||
SRLV $2, R25, R28
|
||||
SRLV $2, R26, R26
|
||||
OR R27, R28, R25
|
||||
ADDV R25, R8, R8
|
||||
ADDV R26, R9, R27
|
||||
SGTU R25, R8, R24
|
||||
SGTU R26, R27, R28
|
||||
ADDV R27, R24, R9
|
||||
SGTU R27, R9, R24
|
||||
OR R24, R28, R24
|
||||
ADDV R24, R10, R10
|
||||
|
||||
SUBV $16, R6, R6
|
||||
BGE R6, R7, loop
|
||||
|
||||
bytes_between_0_and_15:
|
||||
BEQ R6, R0, done
|
||||
MOVV $1, R14
|
||||
XOR R15, R15
|
||||
ADDV R6, R5, R5
|
||||
|
||||
flush_buffer:
|
||||
MOVBU -1(R5), R25
|
||||
SRLV $56, R14, R24
|
||||
SLLV $8, R15, R28
|
||||
SLLV $8, R14, R14
|
||||
OR R24, R28, R15
|
||||
XOR R25, R14, R14
|
||||
SUBV $1, R6, R6
|
||||
SUBV $1, R5, R5
|
||||
BNE R6, R0, flush_buffer
|
||||
|
||||
ADDV R14, R8, R8
|
||||
SGTU R14, R8, R24
|
||||
ADDV R15, R9, R27
|
||||
SGTU R15, R27, R28
|
||||
ADDV R27, R24, R9
|
||||
SGTU R27, R9, R24
|
||||
OR R24, R28, R24
|
||||
ADDV R10, R24, R10
|
||||
|
||||
MOVV $16, R6
|
||||
JMP multiply
|
||||
|
||||
done:
|
||||
MOVV R8, (R4)
|
||||
MOVV R9, 8(R4)
|
||||
MOVV R10, 16(R4)
|
||||
RET
|
||||
@@ -1,47 +0,0 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
//go:build gc && !purego && (ppc64 || ppc64le)
|
||||
|
||||
package poly1305
|
||||
|
||||
//go:noescape
|
||||
func update(state *macState, msg []byte)
|
||||
|
||||
// mac is a wrapper for macGeneric that redirects calls that would have gone to
|
||||
// updateGeneric to update.
|
||||
//
|
||||
// Its Write and Sum methods are otherwise identical to the macGeneric ones, but
|
||||
// using function pointers would carry a major performance cost.
|
||||
type mac struct{ macGeneric }
|
||||
|
||||
func (h *mac) Write(p []byte) (int, error) {
|
||||
nn := len(p)
|
||||
if h.offset > 0 {
|
||||
n := copy(h.buffer[h.offset:], p)
|
||||
if h.offset+n < TagSize {
|
||||
h.offset += n
|
||||
return nn, nil
|
||||
}
|
||||
p = p[n:]
|
||||
h.offset = 0
|
||||
update(&h.macState, h.buffer[:])
|
||||
}
|
||||
if n := len(p) - (len(p) % TagSize); n > 0 {
|
||||
update(&h.macState, p[:n])
|
||||
p = p[n:]
|
||||
}
|
||||
if len(p) > 0 {
|
||||
h.offset += copy(h.buffer[h.offset:], p)
|
||||
}
|
||||
return nn, nil
|
||||
}
|
||||
|
||||
func (h *mac) Sum(out *[16]byte) {
|
||||
state := h.macState
|
||||
if h.offset > 0 {
|
||||
update(&state, h.buffer[:h.offset])
|
||||
}
|
||||
finalize(out, &state.h, &state.s)
|
||||
}
|
||||
+1
-2
@@ -5,7 +5,6 @@
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -501,7 +500,7 @@ func (t *handshakeTransport) sendKexInit() error {
|
||||
CompressionClientServer: supportedCompressions,
|
||||
CompressionServerClient: supportedCompressions,
|
||||
}
|
||||
io.ReadFull(rand.Reader, msg.Cookie[:])
|
||||
io.ReadFull(t.config.Rand, msg.Cookie[:])
|
||||
|
||||
// We mutate the KexAlgos slice, in order to add the kex-strict extension algorithm,
|
||||
// and possibly to add the ext-info extension algorithm. Since the slice may be the
|
||||
|
||||
@@ -302,8 +302,8 @@ func (k *KnownKey) String() string {
|
||||
// applications can offer an interactive prompt to the user.
|
||||
type KeyError struct {
|
||||
// Want holds the accepted host keys. For each key algorithm,
|
||||
// there can be one hostkey. If Want is empty, the host is
|
||||
// unknown. If Want is non-empty, there was a mismatch, which
|
||||
// there can be multiple hostkeys. If Want is empty, the host
|
||||
// is unknown. If Want is non-empty, there was a mismatch, which
|
||||
// can signify a MITM attack.
|
||||
Want []KnownKey
|
||||
}
|
||||
@@ -358,34 +358,20 @@ func (db *hostKeyDB) checkAddr(a addr, remoteKey ssh.PublicKey) error {
|
||||
// is just a key for the IP address, but not for the
|
||||
// hostname?
|
||||
|
||||
// Algorithm => key.
|
||||
knownKeys := map[string]KnownKey{}
|
||||
keyErr := &KeyError{}
|
||||
|
||||
for _, l := range db.lines {
|
||||
if l.match(a) {
|
||||
typ := l.knownKey.Key.Type()
|
||||
if _, ok := knownKeys[typ]; !ok {
|
||||
knownKeys[typ] = l.knownKey
|
||||
}
|
||||
if !l.match(a) {
|
||||
continue
|
||||
}
|
||||
|
||||
keyErr.Want = append(keyErr.Want, l.knownKey)
|
||||
if keyEq(l.knownKey.Key, remoteKey) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
keyErr := &KeyError{}
|
||||
for _, v := range knownKeys {
|
||||
keyErr.Want = append(keyErr.Want, v)
|
||||
}
|
||||
|
||||
// Unknown remote host.
|
||||
if len(knownKeys) == 0 {
|
||||
return keyErr
|
||||
}
|
||||
|
||||
// If the remote host starts using a different, unknown key type, we
|
||||
// also interpret that as a mismatch.
|
||||
if known, ok := knownKeys[remoteKey.Type()]; !ok || !keyEq(known.Key, remoteKey) {
|
||||
return keyErr
|
||||
}
|
||||
|
||||
return nil
|
||||
return keyErr
|
||||
}
|
||||
|
||||
// The Read function parses file contents.
|
||||
|
||||
@@ -201,17 +201,6 @@ func TestHostNamePrecedence(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDBOrderingPrecedenceKeyType(t *testing.T) {
|
||||
str := fmt.Sprintf("server.org,%s %s\nserver.org,%s %s", testAddr, edKeyStr, testAddr, alternateEdKeyStr)
|
||||
db := testDB(t, str)
|
||||
|
||||
if err := db.check("server.org:22", testAddr, alternateEdKey); err == nil {
|
||||
t.Errorf("check succeeded")
|
||||
} else if _, ok := err.(*KeyError); !ok {
|
||||
t.Errorf("got %T, want *KeyError", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNegate(t *testing.T) {
|
||||
str := fmt.Sprintf("%s,!server.org %s", testAddr, edKeyStr)
|
||||
db := testDB(t, str)
|
||||
@@ -354,3 +343,16 @@ func TestHashedHostkeyCheck(t *testing.T) {
|
||||
t.Errorf("got error %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssue36126(t *testing.T) {
|
||||
str := fmt.Sprintf("server.org,%s %s\nserver.org,%s %s", testAddr, edKeyStr, testAddr, alternateEdKeyStr)
|
||||
db := testDB(t, str)
|
||||
|
||||
if err := db.check("server.org:22", testAddr, edKey); err != nil {
|
||||
t.Errorf("should have passed the check, got %v", err)
|
||||
}
|
||||
|
||||
if err := db.check("server.org:22", testAddr, alternateEdKey); err != nil {
|
||||
t.Errorf("should have passed the check, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
+1155
-439
File diff suppressed because it is too large
Load Diff
@@ -22,8 +22,19 @@ import "crypto/x509"
|
||||
|
||||
func init() {
|
||||
p := x509.NewCertPool()
|
||||
for _, c := range bundle {
|
||||
p.AddCert(c)
|
||||
for _, c := range parsedCertificates {
|
||||
if len(c.constraints) == 0 {
|
||||
p.AddCert(c.cert)
|
||||
} else {
|
||||
p.AddCertWithConstraint(c.cert, func(chain []*x509.Certificate) error {
|
||||
for _, constraint := range c.constraints {
|
||||
if err := constraint(chain); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
}
|
||||
x509.SetFallbackRoots(p)
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/x509roots/nss"
|
||||
)
|
||||
@@ -29,36 +30,68 @@ const tmpl = `// Code generated by gen_fallback_bundle.go; DO NOT EDIT.
|
||||
|
||||
package fallback
|
||||
|
||||
import "crypto/x509"
|
||||
import "encoding/pem"
|
||||
import (
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func mustParse(b []byte) []*x509.Certificate {
|
||||
var roots []*x509.Certificate
|
||||
for len(b) > 0 {
|
||||
var block *pem.Block
|
||||
block, b = pem.Decode(b)
|
||||
type unparsedCertificate struct {
|
||||
cn string
|
||||
sha256Hash string
|
||||
pem string
|
||||
|
||||
// possible constraints
|
||||
distrustAfter string
|
||||
}
|
||||
|
||||
type parsedCertificate struct {
|
||||
cert *x509.Certificate
|
||||
constraints []func([]*x509.Certificate) error
|
||||
}
|
||||
|
||||
func mustParse(unparsedCerts []unparsedCertificate) []parsedCertificate {
|
||||
var b []parsedCertificate
|
||||
for _, unparsed := range unparsedCerts {
|
||||
block, rest := pem.Decode([]byte(unparsed.pem))
|
||||
if block == nil {
|
||||
break
|
||||
panic(fmt.Sprintf("unexpected nil PEM block for %q", unparsed.cn))
|
||||
}
|
||||
if len(rest) != 0 {
|
||||
panic(fmt.Sprintf("unexpected trailing data in PEM for %q", unparsed.cn))
|
||||
}
|
||||
if block.Type != "CERTIFICATE" {
|
||||
panic("unexpected PEM block type: " + block.Type)
|
||||
panic(fmt.Sprintf("unexpected PEM block type for %q: %s", unparsed.cn, block.Type))
|
||||
}
|
||||
cert, err := x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
roots = append(roots, cert)
|
||||
parsed := parsedCertificate{cert: cert}
|
||||
// parse possible constraints, this should check all fields of unparsedCertificate.
|
||||
if unparsed.distrustAfter != "" {
|
||||
distrustAfter, err := time.Parse(time.RFC3339, unparsed.distrustAfter)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to parse distrustAfter %q: %s", unparsed.distrustAfter, err))
|
||||
}
|
||||
parsed.constraints = append(parsed.constraints, func(chain []*x509.Certificate) error {
|
||||
for _, c := range chain {
|
||||
if c.NotBefore.After(distrustAfter) {
|
||||
return fmt.Errorf("certificate issued after distrust-after date %q", distrustAfter)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
b = append(b, parsed)
|
||||
}
|
||||
return roots
|
||||
return b
|
||||
}
|
||||
|
||||
var bundle = mustParse([]byte(pemRoots))
|
||||
|
||||
// Format of the PEM list is:
|
||||
// * Subject common name
|
||||
// * SHA256 hash
|
||||
// * PEM block
|
||||
var parsedCertificates = mustParse(unparsedCertificates)
|
||||
|
||||
var unparsedCertificates = []unparsedCertificate{
|
||||
`
|
||||
|
||||
var (
|
||||
@@ -122,19 +155,33 @@ func main() {
|
||||
|
||||
b := new(bytes.Buffer)
|
||||
b.WriteString(tmpl)
|
||||
fmt.Fprintln(b, "const pemRoots = `")
|
||||
for _, c := range certs {
|
||||
if len(c.Constraints) > 0 {
|
||||
// Until the constrained roots API lands, skip anything that has any
|
||||
// additional constraints. Once that API is available, we can add
|
||||
// build constraints that support both the current version and the
|
||||
// new version.
|
||||
var constraints []string
|
||||
var skip bool
|
||||
for _, constraint := range c.Constraints {
|
||||
switch t := constraint.(type) {
|
||||
case nss.DistrustAfter:
|
||||
constraints = append(constraints, fmt.Sprintf("distrustAfter: \"%s\",", time.Time(t).Format(time.RFC3339)))
|
||||
default:
|
||||
// If we encounter any constraints we don't support, skip the certificate.
|
||||
skip = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if skip {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(b, "# %s\n# %x\n", c.X509.Subject.String(), sha256.Sum256(c.X509.Raw))
|
||||
pem.Encode(b, &pem.Block{Type: "CERTIFICATE", Bytes: c.X509.Raw})
|
||||
fmt.Fprintf(b, "{\ncn: %q,\nsha256Hash: \"%x\",\npem: `%s`,\n",
|
||||
c.X509.Subject.String(),
|
||||
sha256.Sum256(c.X509.Raw),
|
||||
string(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: c.X509.Raw})),
|
||||
)
|
||||
for _, constraint := range constraints {
|
||||
fmt.Fprintln(b, constraint)
|
||||
}
|
||||
fmt.Fprintln(b, "},")
|
||||
}
|
||||
fmt.Fprintln(b, "`")
|
||||
fmt.Fprintln(b, "}")
|
||||
|
||||
formatted, err := format.Source(b.Bytes())
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user