import (
"crypto/cipher"
+ subtleoverlap "crypto/internal/subtle"
"crypto/subtle"
"errors"
)
// details.
func (g *gcmAsm) Seal(dst, nonce, plaintext, data []byte) []byte {
if len(nonce) != g.nonceSize {
- panic("cipher: incorrect nonce length given to GCM")
+ panic("crypto/cipher: incorrect nonce length given to GCM")
}
if uint64(len(plaintext)) > ((1<<32)-2)*BlockSize {
- panic("cipher: message too large for GCM")
+ panic("crypto/cipher: message too large for GCM")
}
var counter, tagMask [gcmBlockSize]byte
gcmAesData(&g.productTable, data, &tagOut)
ret, out := sliceForAppend(dst, len(plaintext)+g.tagSize)
+ if subtleoverlap.InexactOverlap(out[:len(plaintext)], plaintext) {
+ panic("crypto/cipher: invalid buffer overlap")
+ }
if len(plaintext) > 0 {
gcmAesEnc(&g.productTable, out, plaintext, &counter, &tagOut, g.ks)
}
// for details.
func (g *gcmAsm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
if len(nonce) != g.nonceSize {
- panic("cipher: incorrect nonce length given to GCM")
+ panic("crypto/cipher: incorrect nonce length given to GCM")
}
// Sanity check to prevent the authentication from always succeeding if an implementation
// leaves tagSize uninitialized, for example.
if g.tagSize < gcmMinimumTagSize {
- panic("cipher: incorrect GCM tag size")
+ panic("crypto/cipher: incorrect GCM tag size")
}
if len(ciphertext) < g.tagSize {
gcmAesData(&g.productTable, data, &expectedTag)
ret, out := sliceForAppend(dst, len(ciphertext))
+ if subtleoverlap.InexactOverlap(out, ciphertext) {
+ panic("crypto/cipher: invalid buffer overlap")
+ }
if len(ciphertext) > 0 {
gcmAesDec(&g.productTable, out, ciphertext, &counter, &expectedTag, g.ks)
}
import (
"crypto/cipher"
+ "crypto/internal/subtle"
)
// Assert that aesCipherAsm implements the cbcEncAble and cbcDecAble interfaces.
if len(dst) < len(src) {
panic("crypto/cipher: output smaller than input")
}
+ if subtle.InexactOverlap(dst[:len(src)], src) {
+ panic("crypto/cipher: invalid buffer overlap")
+ }
if len(src) > 0 {
cryptBlocksChain(x.c, &x.iv[0], &x.b.key[0], &dst[0], &src[0], len(src))
}
import (
"crypto/cipher"
+ "crypto/internal/subtle"
"strconv"
)
if len(dst) < BlockSize {
panic("crypto/aes: output not full block")
}
+ if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
+ panic("crypto/aes: invalid buffer overlap")
+ }
encryptBlockGo(c.enc, dst, src)
}
if len(dst) < BlockSize {
panic("crypto/aes: output not full block")
}
+ if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
+ panic("crypto/aes: invalid buffer overlap")
+ }
decryptBlockGo(c.dec, dst, src)
}
import (
"crypto/cipher"
+ "crypto/internal/subtle"
"internal/cpu"
)
if len(dst) < BlockSize {
panic("crypto/aes: output not full block")
}
+ if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
+ panic("crypto/aes: invalid buffer overlap")
+ }
encryptBlockAsm(len(c.enc)/4-1, &c.enc[0], &dst[0], &src[0])
}
if len(dst) < BlockSize {
panic("crypto/aes: output not full block")
}
+ if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
+ panic("crypto/aes: invalid buffer overlap")
+ }
decryptBlockAsm(len(c.dec)/4-1, &c.dec[0], &dst[0], &src[0])
}
import (
"crypto/cipher"
+ "crypto/internal/subtle"
"internal/cpu"
"math/bits"
)
if len(dst) < BlockSize {
panic("crypto/aes: output not full block")
}
+ if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
+ panic("crypto/aes: invalid buffer overlap")
+ }
encryptBlockAsm(len(c.enc)/4-1, &c.enc[0], &dst[0], &src[0])
}
if len(dst) < BlockSize {
panic("crypto/aes: output not full block")
}
+ if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
+ panic("crypto/aes: invalid buffer overlap")
+ }
decryptBlockAsm(len(c.dec)/4-1, &c.dec[0], &dst[0], &src[0])
}
import (
"crypto/cipher"
+ "crypto/internal/subtle"
)
// defined in asm_ppc64le.s
if len(dst) < BlockSize {
panic("crypto/aes: output not full block")
}
+ if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
+ panic("crypto/aes: invalid buffer overlap")
+ }
encryptBlockAsm(&dst[0], &src[0], &c.enc[0])
}
if len(dst) < BlockSize {
panic("crypto/aes: output not full block")
}
+ if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
+ panic("crypto/aes: invalid buffer overlap")
+ }
decryptBlockAsm(&dst[0], &src[0], &c.dec[0])
}
import (
"crypto/cipher"
+ "crypto/internal/subtle"
"internal/cpu"
)
if len(dst) < BlockSize {
panic("crypto/aes: output not full block")
}
+ if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
+ panic("crypto/aes: invalid buffer overlap")
+ }
cryptBlocks(c.function, &c.key[0], &dst[0], &src[0], BlockSize)
}
if len(dst) < BlockSize {
panic("crypto/aes: output not full block")
}
+ if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
+ panic("crypto/aes: invalid buffer overlap")
+ }
// The decrypt function code is equal to the function code + 128.
cryptBlocks(c.function+128, &c.key[0], &dst[0], &src[0], BlockSize)
}
import (
"crypto/cipher"
+ "crypto/internal/subtle"
"unsafe"
)
}
func (c *aesctr) XORKeyStream(dst, src []byte) {
- if len(src) > 0 {
- // Assert len(dst) >= len(src)
- _ = dst[len(src)-1]
+ if len(dst) < len(src) {
+ panic("crypto/cipher: output smaller than input")
+ }
+ if subtle.InexactOverlap(dst[:len(src)], src) {
+ panic("crypto/cipher: invalid buffer overlap")
}
for len(src) > 0 {
if len(c.buffer) == 0 {
import (
"crypto/cipher"
+ subtleoverlap "crypto/internal/subtle"
"crypto/subtle"
"errors"
"internal/cpu"
// details.
func (g *gcmAsm) Seal(dst, nonce, plaintext, data []byte) []byte {
if len(nonce) != g.nonceSize {
- panic("cipher: incorrect nonce length given to GCM")
+ panic("crypto/cipher: incorrect nonce length given to GCM")
}
if uint64(len(plaintext)) > ((1<<32)-2)*BlockSize {
- panic("cipher: message too large for GCM")
+ panic("crypto/cipher: message too large for GCM")
}
ret, out := sliceForAppend(dst, len(plaintext)+g.tagSize)
+ if subtleoverlap.InexactOverlap(out[:len(plaintext)], plaintext) {
+ panic("crypto/cipher: invalid buffer overlap")
+ }
counter := g.deriveCounter(nonce)
// for details.
func (g *gcmAsm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
if len(nonce) != g.nonceSize {
- panic("cipher: incorrect nonce length given to GCM")
+ panic("crypto/cipher: incorrect nonce length given to GCM")
}
// Sanity check to prevent the authentication from always succeeding if an implementation
// leaves tagSize uninitialized, for example.
if g.tagSize < gcmMinimumTagSize {
- panic("cipher: incorrect GCM tag size")
+ panic("crypto/cipher: incorrect GCM tag size")
}
if len(ciphertext) < g.tagSize {
return nil, errOpen
g.auth(expectedTag[:], ciphertext, data, &tagMask)
ret, out := sliceForAppend(dst, len(ciphertext))
+ if subtleoverlap.InexactOverlap(out, ciphertext) {
+ panic("crypto/cipher: invalid buffer overlap")
+ }
if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 {
// The AESNI code decrypts and authenticates concurrently, and
// details.
func (g *gcmKMA) Seal(dst, nonce, plaintext, data []byte) []byte {
if len(nonce) != g.nonceSize {
- panic("cipher: incorrect nonce length given to GCM")
+ panic("crypto/cipher: incorrect nonce length given to GCM")
}
if uint64(len(plaintext)) > ((1<<32)-2)*BlockSize {
- panic("cipher: message too large for GCM")
+ panic("crypto/cipher: message too large for GCM")
}
ret, out := sliceForAppend(dst, len(plaintext)+g.tagSize)
+ if subtleoverlap.InexactOverlap(out[:len(plaintext)], plaintext) {
+ panic("crypto/cipher: invalid buffer overlap")
+ }
counter := g.deriveCounter(nonce)
fc := g.block.function | kmaLAAD | kmaLPC
// for details.
func (g *gcmKMA) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
if len(nonce) != g.nonceSize {
- panic("cipher: incorrect nonce length given to GCM")
+ panic("crypto/cipher: incorrect nonce length given to GCM")
}
if len(ciphertext) < g.tagSize {
return nil, errOpen
tag := ciphertext[len(ciphertext)-g.tagSize:]
ciphertext = ciphertext[:len(ciphertext)-g.tagSize]
ret, out := sliceForAppend(dst, len(ciphertext))
+ if subtleoverlap.InexactOverlap(out, ciphertext) {
+ panic("crypto/cipher: invalid buffer overlap")
+ }
if g.tagSize < gcmMinimumTagSize {
- panic("cipher: incorrect GCM tag size")
+ panic("crypto/cipher: incorrect GCM tag size")
}
counter := g.deriveCounter(nonce)
package cipher
+import "crypto/internal/subtle"
+
type cbc struct {
b Block
blockSize int
if len(dst) < len(src) {
panic("crypto/cipher: output smaller than input")
}
+ if subtle.InexactOverlap(dst[:len(src)], src) {
+ panic("crypto/cipher: invalid buffer overlap")
+ }
iv := x.iv
if len(dst) < len(src) {
panic("crypto/cipher: output smaller than input")
}
+ if subtle.InexactOverlap(dst[:len(src)], src) {
+ panic("crypto/cipher: invalid buffer overlap")
+ }
if len(src) == 0 {
return
}
package cipher
+import "crypto/internal/subtle"
+
type cfb struct {
b Block
next []byte
}
func (x *cfb) XORKeyStream(dst, src []byte) {
+ if len(dst) < len(src) {
+ panic("crypto/cipher: output smaller than input")
+ }
+ if subtle.InexactOverlap(dst[:len(src)], src) {
+ panic("crypto/cipher: invalid buffer overlap")
+ }
for len(src) > 0 {
if x.outUsed == len(x.out) {
x.b.Encrypt(x.out, x.next)
package cipher
+import "crypto/internal/subtle"
+
type ctr struct {
b Block
ctr []byte
}
func (x *ctr) XORKeyStream(dst, src []byte) {
+ if len(dst) < len(src) {
+ panic("crypto/cipher: output smaller than input")
+ }
+ if subtle.InexactOverlap(dst[:len(src)], src) {
+ panic("crypto/cipher: invalid buffer overlap")
+ }
for len(src) > 0 {
if x.outUsed >= len(x.out)-x.b.BlockSize() {
x.refill()
package cipher
import (
+ subtleoverlap "crypto/internal/subtle"
"crypto/subtle"
"errors"
)
// slice. The nonce must be NonceSize() bytes long and unique for all
// time, for a given key.
//
- // The plaintext and dst must overlap exactly or not at all. To reuse
- // plaintext's storage for the encrypted output, use plaintext[:0] as dst.
+ // To reuse plaintext's storage for the encrypted output, use plaintext[:0]
+ // as dst. Otherwise, the remaining capacity of dst must not overlap plaintext.
Seal(dst, nonce, plaintext, additionalData []byte) []byte
// Open decrypts and authenticates ciphertext, authenticates the
// bytes long and both it and the additional data must match the
// value passed to Seal.
//
- // The ciphertext and dst must overlap exactly or not at all. To reuse
- // ciphertext's storage for the decrypted output, use ciphertext[:0] as dst.
+ // To reuse ciphertext's storage for the decrypted output, use ciphertext[:0]
+ // as dst. Otherwise, the remaining capacity of dst must not overlap plaintext.
//
// Even if the function fails, the contents of dst, up to its capacity,
// may be overwritten.
func (g *gcm) Seal(dst, nonce, plaintext, data []byte) []byte {
if len(nonce) != g.nonceSize {
- panic("cipher: incorrect nonce length given to GCM")
+ panic("crypto/cipher: incorrect nonce length given to GCM")
}
if uint64(len(plaintext)) > ((1<<32)-2)*uint64(g.cipher.BlockSize()) {
- panic("cipher: message too large for GCM")
+ panic("crypto/cipher: message too large for GCM")
}
ret, out := sliceForAppend(dst, len(plaintext)+g.tagSize)
+ if subtleoverlap.InexactOverlap(out, plaintext) {
+ panic("crypto/cipher: invalid buffer overlap")
+ }
var counter, tagMask [gcmBlockSize]byte
g.deriveCounter(&counter, nonce)
func (g *gcm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
if len(nonce) != g.nonceSize {
- panic("cipher: incorrect nonce length given to GCM")
+ panic("crypto/cipher: incorrect nonce length given to GCM")
}
// Sanity check to prevent the authentication from always succeeding if an implementation
// leaves tagSize uninitialized, for example.
if g.tagSize < gcmMinimumTagSize {
- panic("cipher: incorrect GCM tag size")
+ panic("crypto/cipher: incorrect GCM tag size")
}
if len(ciphertext) < g.tagSize {
g.auth(expectedTag[:], ciphertext, data, &tagMask)
ret, out := sliceForAppend(dst, len(ciphertext))
+ if subtleoverlap.InexactOverlap(out, ciphertext) {
+ panic("crypto/cipher: invalid buffer overlap")
+ }
if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 {
// The AESNI code decrypts and authenticates concurrently, and
package cipher
+import "crypto/internal/subtle"
+
type ofb struct {
b Block
cipher []byte
}
func (x *ofb) XORKeyStream(dst, src []byte) {
+ if len(dst) < len(src) {
+ panic("crypto/cipher: output smaller than input")
+ }
+ if subtle.InexactOverlap(dst[:len(src)], src) {
+ panic("crypto/cipher: invalid buffer overlap")
+ }
for len(src) > 0 {
if x.outUsed >= len(x.out)-x.b.BlockSize() {
x.refill()
import (
"crypto/cipher"
+ "crypto/internal/subtle"
"encoding/binary"
"strconv"
)
func (c *desCipher) BlockSize() int { return BlockSize }
-func (c *desCipher) Encrypt(dst, src []byte) { encryptBlock(c.subkeys[:], dst, src) }
+func (c *desCipher) Encrypt(dst, src []byte) {
+ if len(src) < BlockSize {
+ panic("crypto/des: input not full block")
+ }
+ if len(dst) < BlockSize {
+ panic("crypto/des: output not full block")
+ }
+ if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
+ panic("crypto/des: invalid buffer overlap")
+ }
+ encryptBlock(c.subkeys[:], dst, src)
+}
-func (c *desCipher) Decrypt(dst, src []byte) { decryptBlock(c.subkeys[:], dst, src) }
+func (c *desCipher) Decrypt(dst, src []byte) {
+ if len(src) < BlockSize {
+ panic("crypto/des: input not full block")
+ }
+ if len(dst) < BlockSize {
+ panic("crypto/des: output not full block")
+ }
+ if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
+ panic("crypto/des: invalid buffer overlap")
+ }
+ decryptBlock(c.subkeys[:], dst, src)
+}
// A tripleDESCipher is an instance of TripleDES encryption.
type tripleDESCipher struct {
func (c *tripleDESCipher) BlockSize() int { return BlockSize }
func (c *tripleDESCipher) Encrypt(dst, src []byte) {
+ if len(src) < BlockSize {
+ panic("crypto/des: input not full block")
+ }
+ if len(dst) < BlockSize {
+ panic("crypto/des: output not full block")
+ }
+ if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
+ panic("crypto/des: invalid buffer overlap")
+ }
+
b := binary.BigEndian.Uint64(src)
b = permuteInitialBlock(b)
left, right := uint32(b>>32), uint32(b)
}
func (c *tripleDESCipher) Decrypt(dst, src []byte) {
+ if len(src) < BlockSize {
+ panic("crypto/des: input not full block")
+ }
+ if len(dst) < BlockSize {
+ panic("crypto/des: output not full block")
+ }
+ if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
+ panic("crypto/des: invalid buffer overlap")
+ }
+
b := binary.BigEndian.Uint64(src)
b = permuteInitialBlock(b)
left, right := uint32(b>>32), uint32(b)
--- /dev/null
+// Copyright 2018 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.
+
+// +build !appengine
+
+// Package subtle implements functions that are often useful in cryptographic
+// code but require careful thought to use correctly.
+//
+// This is a mirror of golang.org/x/crypto/internal/subtle.
+package subtle // import "crypto/internal/subtle"
+
+import "unsafe"
+
+// AnyOverlap reports whether x and y share memory at any (not necessarily
+// corresponding) index. The memory beyond the slice length is ignored.
+func AnyOverlap(x, y []byte) bool {
+ return len(x) > 0 && len(y) > 0 &&
+ uintptr(unsafe.Pointer(&x[0])) <= uintptr(unsafe.Pointer(&y[len(y)-1])) &&
+ uintptr(unsafe.Pointer(&y[0])) <= uintptr(unsafe.Pointer(&x[len(x)-1]))
+}
+
+// InexactOverlap reports whether x and y share memory at any non-corresponding
+// index. The memory beyond the slice length is ignored. Note that x and y can
+// have different lengths and still not have any inexact overlap.
+//
+// InexactOverlap can be used to implement the requirements of the crypto/cipher
+// AEAD, Block, BlockMode and Stream interfaces.
+func InexactOverlap(x, y []byte) bool {
+ if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] {
+ return false
+ }
+ return AnyOverlap(x, y)
+}
--- /dev/null
+// Copyright 2018 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.
+
+// +build appengine
+
+// Package subtle implements functions that are often useful in cryptographic
+// code but require careful thought to use correctly.
+//
+// This is a mirror of golang.org/x/crypto/internal/subtle.
+package subtle // import "crypto/internal/subtle"
+
+// This is the Google App Engine standard variant based on reflect
+// because the unsafe package and cgo are disallowed.
+
+import "reflect"
+
+// AnyOverlap reports whether x and y share memory at any (not necessarily
+// corresponding) index. The memory beyond the slice length is ignored.
+func AnyOverlap(x, y []byte) bool {
+ return len(x) > 0 && len(y) > 0 &&
+ reflect.ValueOf(&x[0]).Pointer() <= reflect.ValueOf(&y[len(y)-1]).Pointer() &&
+ reflect.ValueOf(&y[0]).Pointer() <= reflect.ValueOf(&x[len(x)-1]).Pointer()
+}
+
+// InexactOverlap reports whether x and y share memory at any non-corresponding
+// index. The memory beyond the slice length is ignored. Note that x and y can
+// have different lengths and still not have any inexact overlap.
+//
+// InexactOverlap can be used to implement the requirements of the crypto/cipher
+// AEAD, Block, BlockMode and Stream interfaces.
+func InexactOverlap(x, y []byte) bool {
+ if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] {
+ return false
+ }
+ return AnyOverlap(x, y)
+}
--- /dev/null
+// Copyright 2018 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 subtle_test
+
+import (
+ "testing"
+
+ "crypto/internal/subtle"
+)
+
+var a, b [100]byte
+
+var aliasingTests = []struct {
+ x, y []byte
+ anyOverlap, inexactOverlap bool
+}{
+ {a[:], b[:], false, false},
+ {a[:], b[:0], false, false},
+ {a[:], b[:50], false, false},
+ {a[40:50], a[50:60], false, false},
+ {a[40:50], a[60:70], false, false},
+ {a[:51], a[50:], true, true},
+ {a[:], a[:], true, false},
+ {a[:50], a[:60], true, false},
+ {a[:], nil, false, false},
+ {nil, nil, false, false},
+ {a[:], a[:0], false, false},
+ {a[:10], a[:10:20], true, false},
+ {a[:10], a[5:10:20], true, true},
+}
+
+func testAliasing(t *testing.T, i int, x, y []byte, anyOverlap, inexactOverlap bool) {
+ any := subtle.AnyOverlap(x, y)
+ if any != anyOverlap {
+ t.Errorf("%d: wrong AnyOverlap result, expected %v, got %v", i, anyOverlap, any)
+ }
+ inexact := subtle.InexactOverlap(x, y)
+ if inexact != inexactOverlap {
+ t.Errorf("%d: wrong InexactOverlap result, expected %v, got %v", i, inexactOverlap, any)
+ }
+}
+
+func TestAliasing(t *testing.T) {
+ for i, tt := range aliasingTests {
+ testAliasing(t, i, tt.x, tt.y, tt.anyOverlap, tt.inexactOverlap)
+ testAliasing(t, i, tt.y, tt.x, tt.anyOverlap, tt.inexactOverlap)
+ }
+}
// applications.
package rc4
-import "strconv"
+import (
+ "crypto/internal/subtle"
+ "strconv"
+)
// A Cipher is an instance of RC4 using a particular key.
type Cipher struct {
if len(src) == 0 {
return
}
+ if subtle.InexactOverlap(dst[:len(src)], src) {
+ panic("crypto/rc4: invalid buffer overlap")
+ }
i, j := c.i, c.j
_ = dst[len(src)-1]
dst = dst[:len(src)] // eliminate bounds check from loop
package rc4
+import "crypto/internal/subtle"
+
func xorKeyStream(dst, src *byte, n int, state *[256]uint32, i, j *uint8)
// XORKeyStream sets dst to the result of XORing src with the key stream.
if len(src) == 0 {
return
}
- // Assert len(dst) >= len(src)
- _ = dst[len(src)-1]
+ if len(dst) < len(src) {
+ panic("crypto/cipher: output smaller than input")
+ }
+ if subtle.InexactOverlap(dst[:len(src)], src) {
+ panic("crypto/cipher: invalid buffer overlap")
+ }
xorKeyStream(&dst[0], &src[0], len(src), &c.s, &c.i, &c.j)
}
// L3 adds reflection and some basic utility packages
// and interface definitions, but nothing that makes
// system calls.
- "crypto": {"L2", "hash"}, // interfaces
- "crypto/cipher": {"L2", "crypto/subtle"},
- "crypto/subtle": {},
- "encoding/base32": {"L2"},
- "encoding/base64": {"L2", "encoding/binary"},
- "encoding/binary": {"L2", "reflect"},
- "hash": {"L2"}, // interfaces
- "hash/adler32": {"L2", "hash"},
- "hash/crc32": {"L2", "hash"},
- "hash/crc64": {"L2", "hash"},
- "hash/fnv": {"L2", "hash"},
- "image": {"L2", "image/color"}, // interfaces
- "image/color": {"L2"}, // interfaces
- "image/color/palette": {"L2", "image/color"},
- "reflect": {"L2"},
- "sort": {"reflect"},
+ "crypto": {"L2", "hash"}, // interfaces
+ "crypto/cipher": {"L2", "crypto/subtle", "crypto/internal/subtle"},
+ "crypto/internal/subtle": {"unsafe", "reflect"}, // reflect behind a appengine tag
+ "crypto/subtle": {},
+ "encoding/base32": {"L2"},
+ "encoding/base64": {"L2", "encoding/binary"},
+ "encoding/binary": {"L2", "reflect"},
+ "hash": {"L2"}, // interfaces
+ "hash/adler32": {"L2", "hash"},
+ "hash/crc32": {"L2", "hash"},
+ "hash/crc64": {"L2", "hash"},
+ "hash/fnv": {"L2", "hash"},
+ "image": {"L2", "image/color"}, // interfaces
+ "image/color": {"L2"}, // interfaces
+ "image/color/palette": {"L2", "image/color"},
+ "reflect": {"L2"},
+ "sort": {"reflect"},
"L3": {
"L2",
"crypto",
"crypto/cipher",
+ "crypto/internal/subtle",
"crypto/subtle",
"encoding/base32",
"encoding/base64",
"go/types": {"L4", "GOPARSER", "container/heap", "go/constant"},
// One of a kind.
- "archive/tar": {"L4", "OS", "syscall", "os/user"},
- "archive/zip": {"L4", "OS", "compress/flate"},
- "container/heap": {"sort"},
- "compress/bzip2": {"L4"},
- "compress/flate": {"L4"},
- "compress/gzip": {"L4", "compress/flate"},
- "compress/lzw": {"L4"},
- "compress/zlib": {"L4", "compress/flate"},
- "context": {"errors", "fmt", "reflect", "sync", "time"},
- "database/sql": {"L4", "container/list", "context", "database/sql/driver", "database/sql/internal"},
- "database/sql/driver": {"L4", "context", "time", "database/sql/internal"},
- "debug/dwarf": {"L4"},
- "debug/elf": {"L4", "OS", "debug/dwarf", "compress/zlib"},
- "debug/gosym": {"L4"},
- "debug/macho": {"L4", "OS", "debug/dwarf"},
- "debug/pe": {"L4", "OS", "debug/dwarf"},
- "debug/plan9obj": {"L4", "OS"},
- "encoding": {"L4"},
- "encoding/ascii85": {"L4"},
- "encoding/asn1": {"L4", "math/big"},
- "encoding/csv": {"L4"},
- "encoding/gob": {"L4", "OS", "encoding"},
- "encoding/hex": {"L4"},
- "encoding/json": {"L4", "encoding"},
- "encoding/pem": {"L4"},
- "encoding/xml": {"L4", "encoding"},
- "flag": {"L4", "OS"},
- "go/build": {"L4", "OS", "GOPARSER"},
- "html": {"L4"},
- "image/draw": {"L4", "image/internal/imageutil"},
- "image/gif": {"L4", "compress/lzw", "image/color/palette", "image/draw"},
- "image/internal/imageutil": {"L4"},
- "image/jpeg": {"L4", "image/internal/imageutil"},
- "image/png": {"L4", "compress/zlib"},
- "index/suffixarray": {"L4", "regexp"},
- "internal/singleflight": {"sync"},
- "internal/trace": {"L4", "OS"},
- "math/big": {"L4"},
- "mime": {"L4", "OS", "syscall", "internal/syscall/windows/registry"},
- "mime/quotedprintable": {"L4"},
- "net/internal/socktest": {"L4", "OS", "syscall", "internal/syscall/windows"},
- "net/url": {"L4"},
- "plugin": {"L0", "OS", "CGO"},
+ "archive/tar": {"L4", "OS", "syscall", "os/user"},
+ "archive/zip": {"L4", "OS", "compress/flate"},
+ "container/heap": {"sort"},
+ "compress/bzip2": {"L4"},
+ "compress/flate": {"L4"},
+ "compress/gzip": {"L4", "compress/flate"},
+ "compress/lzw": {"L4"},
+ "compress/zlib": {"L4", "compress/flate"},
+ "context": {"errors", "fmt", "reflect", "sync", "time"},
+ "database/sql": {"L4", "container/list", "context", "database/sql/driver", "database/sql/internal"},
+ "database/sql/driver": {"L4", "context", "time", "database/sql/internal"},
+ "debug/dwarf": {"L4"},
+ "debug/elf": {"L4", "OS", "debug/dwarf", "compress/zlib"},
+ "debug/gosym": {"L4"},
+ "debug/macho": {"L4", "OS", "debug/dwarf"},
+ "debug/pe": {"L4", "OS", "debug/dwarf"},
+ "debug/plan9obj": {"L4", "OS"},
+ "encoding": {"L4"},
+ "encoding/ascii85": {"L4"},
+ "encoding/asn1": {"L4", "math/big"},
+ "encoding/csv": {"L4"},
+ "encoding/gob": {"L4", "OS", "encoding"},
+ "encoding/hex": {"L4"},
+ "encoding/json": {"L4", "encoding"},
+ "encoding/pem": {"L4"},
+ "encoding/xml": {"L4", "encoding"},
+ "flag": {"L4", "OS"},
+ "go/build": {"L4", "OS", "GOPARSER"},
+ "html": {"L4"},
+ "image/draw": {"L4", "image/internal/imageutil"},
+ "image/gif": {"L4", "compress/lzw", "image/color/palette", "image/draw"},
+ "image/internal/imageutil": {"L4"},
+ "image/jpeg": {"L4", "image/internal/imageutil"},
+ "image/png": {"L4", "compress/zlib"},
+ "index/suffixarray": {"L4", "regexp"},
+ "internal/singleflight": {"sync"},
+ "internal/trace": {"L4", "OS"},
+ "math/big": {"L4"},
+ "mime": {"L4", "OS", "syscall", "internal/syscall/windows/registry"},
+ "mime/quotedprintable": {"L4"},
+ "net/internal/socktest": {"L4", "OS", "syscall", "internal/syscall/windows"},
+ "net/url": {"L4"},
+ "plugin": {"L0", "OS", "CGO"},
"runtime/pprof/internal/profile": {"L4", "OS", "compress/gzip", "regexp"},
"testing/internal/testdeps": {"L4", "internal/testlog", "runtime/pprof", "regexp"},
"text/scanner": {"L4", "OS"},