mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-13 21:01:29 +08:00
Update to current version of Go library.
From-SVN: r173931
This commit is contained in:
parent
37cb25ed7a
commit
9ff56c9570
@ -1432,7 +1432,7 @@ Type::methods_constructor(Gogo* gogo, Type* methods_type,
|
||||
p != smethods.end();
|
||||
++p)
|
||||
vals->push_back(this->method_constructor(gogo, method_type, p->first,
|
||||
p->second));
|
||||
p->second, only_value_methods));
|
||||
|
||||
return Expression::make_slice_composite_literal(methods_type, vals, bloc);
|
||||
}
|
||||
@ -1444,7 +1444,8 @@ Type::methods_constructor(Gogo* gogo, Type* methods_type,
|
||||
Expression*
|
||||
Type::method_constructor(Gogo*, Type* method_type,
|
||||
const std::string& method_name,
|
||||
const Method* m) const
|
||||
const Method* m,
|
||||
bool only_value_methods) const
|
||||
{
|
||||
source_location bloc = BUILTINS_LOCATION;
|
||||
|
||||
@ -1487,6 +1488,25 @@ Type::method_constructor(Gogo*, Type* method_type,
|
||||
|
||||
++p;
|
||||
go_assert(p->field_name() == "typ");
|
||||
if (!only_value_methods && m->is_value_method())
|
||||
{
|
||||
// This is a value method on a pointer type. Change the type of
|
||||
// the method to use a pointer receiver. The implementation
|
||||
// always uses a pointer receiver anyhow.
|
||||
Type* rtype = mtype->receiver()->type();
|
||||
Type* prtype = Type::make_pointer_type(rtype);
|
||||
Typed_identifier* receiver =
|
||||
new Typed_identifier(mtype->receiver()->name(), prtype,
|
||||
mtype->receiver()->location());
|
||||
mtype = Type::make_function_type(receiver,
|
||||
(mtype->parameters() == NULL
|
||||
? NULL
|
||||
: mtype->parameters()->copy()),
|
||||
(mtype->results() == NULL
|
||||
? NULL
|
||||
: mtype->results()->copy()),
|
||||
mtype->location());
|
||||
}
|
||||
vals->push_back(Expression::make_type_descriptor(mtype, bloc));
|
||||
|
||||
++p;
|
||||
@ -2779,14 +2799,7 @@ Function_type::type_descriptor_params(Type* params_type,
|
||||
+ (receiver != NULL ? 1 : 0));
|
||||
|
||||
if (receiver != NULL)
|
||||
{
|
||||
Type* rtype = receiver->type();
|
||||
// The receiver is always passed as a pointer. FIXME: Is this
|
||||
// right? Should that fact affect the type descriptor?
|
||||
if (rtype->points_to() == NULL)
|
||||
rtype = Type::make_pointer_type(rtype);
|
||||
vals->push_back(Expression::make_type_descriptor(rtype, bloc));
|
||||
}
|
||||
vals->push_back(Expression::make_type_descriptor(receiver->type(), bloc));
|
||||
|
||||
if (params != NULL)
|
||||
{
|
||||
@ -4822,9 +4835,10 @@ Array_type::make_array_type_descriptor_type()
|
||||
Type* uintptr_type = Type::lookup_integer_type("uintptr");
|
||||
|
||||
Struct_type* sf =
|
||||
Type::make_builtin_struct_type(3,
|
||||
Type::make_builtin_struct_type(4,
|
||||
"", tdt,
|
||||
"elem", ptdt,
|
||||
"slice", ptdt,
|
||||
"len", uintptr_type);
|
||||
|
||||
ret = Type::make_builtin_named_type("ArrayType", sf);
|
||||
@ -4890,6 +4904,11 @@ Array_type::array_type_descriptor(Gogo* gogo, Named_type* name)
|
||||
go_assert(p->field_name() == "elem");
|
||||
vals->push_back(Expression::make_type_descriptor(this->element_type_, bloc));
|
||||
|
||||
++p;
|
||||
go_assert(p->field_name() == "slice");
|
||||
Type* slice_type = Type::make_array_type(this->element_type_, NULL);
|
||||
vals->push_back(Expression::make_type_descriptor(slice_type, bloc));
|
||||
|
||||
++p;
|
||||
go_assert(p->field_name() == "len");
|
||||
vals->push_back(Expression::make_cast(p->type(), this->length_, bloc));
|
||||
@ -5375,8 +5394,9 @@ Channel_type::do_make_expression_tree(Translate_context* context,
|
||||
Gogo* gogo = context->gogo();
|
||||
tree channel_type = type_to_tree(this->get_backend(gogo));
|
||||
|
||||
tree element_tree = type_to_tree(this->element_type_->get_backend(gogo));
|
||||
tree element_size_tree = size_in_bytes(element_tree);
|
||||
Type* ptdt = Type::make_type_descriptor_ptr_type();
|
||||
tree element_type_descriptor =
|
||||
this->element_type_->type_descriptor_pointer(gogo);
|
||||
|
||||
tree bad_index = NULL_TREE;
|
||||
|
||||
@ -5402,8 +5422,8 @@ Channel_type::do_make_expression_tree(Translate_context* context,
|
||||
"__go_new_channel",
|
||||
2,
|
||||
channel_type,
|
||||
sizetype,
|
||||
element_size_tree,
|
||||
type_to_tree(ptdt->get_backend(gogo)),
|
||||
element_type_descriptor,
|
||||
sizetype,
|
||||
expr_tree);
|
||||
if (ret == error_mark_node)
|
||||
@ -6242,7 +6262,16 @@ Interface_type::do_reflection(Gogo* gogo, std::string* ret) const
|
||||
if (p != this->methods_->begin())
|
||||
ret->append(";");
|
||||
ret->push_back(' ');
|
||||
ret->append(Gogo::unpack_hidden_name(p->name()));
|
||||
if (!Gogo::is_hidden_name(p->name()))
|
||||
ret->append(p->name());
|
||||
else
|
||||
{
|
||||
// This matches what the gc compiler does.
|
||||
std::string prefix = Gogo::hidden_name_prefix(p->name());
|
||||
ret->append(prefix.substr(prefix.find('.') + 1));
|
||||
ret->push_back('.');
|
||||
ret->append(Gogo::unpack_hidden_name(p->name()));
|
||||
}
|
||||
std::string sub = p->type()->reflection(gogo);
|
||||
go_assert(sub.compare(0, 4, "func") == 0);
|
||||
sub = sub.substr(4);
|
||||
|
@ -1044,7 +1044,7 @@ class Type
|
||||
// Build a composite literal for one method.
|
||||
Expression*
|
||||
method_constructor(Gogo*, Type* method_type, const std::string& name,
|
||||
const Method*) const;
|
||||
const Method*, bool only_value_methods) const;
|
||||
|
||||
static tree
|
||||
build_receive_return_type(tree type);
|
||||
|
@ -8,7 +8,7 @@ package main
|
||||
|
||||
import "reflect"
|
||||
|
||||
func typeof(x interface{}) string { return reflect.Typeof(x).String() }
|
||||
func typeof(x interface{}) string { return reflect.TypeOf(x).String() }
|
||||
|
||||
func f() int { return 0 }
|
||||
|
||||
|
@ -5,23 +5,26 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import "reflect"
|
||||
type S1 struct { i int }
|
||||
type S2 struct { S1 }
|
||||
|
||||
type S1 struct{ i int }
|
||||
type S2 struct{ S1 }
|
||||
|
||||
func main() {
|
||||
typ := reflect.Typeof(S2{}).(*reflect.StructType);
|
||||
f := typ.Field(0);
|
||||
typ := reflect.TypeOf(S2{})
|
||||
f := typ.Field(0)
|
||||
if f.Name != "S1" || f.Anonymous != true {
|
||||
println("BUG: ", f.Name, f.Anonymous);
|
||||
return;
|
||||
println("BUG: ", f.Name, f.Anonymous)
|
||||
return
|
||||
}
|
||||
f, ok := typ.FieldByName("S1");
|
||||
f, ok := typ.FieldByName("S1")
|
||||
if !ok {
|
||||
println("BUG: missing S1");
|
||||
return;
|
||||
println("BUG: missing S1")
|
||||
return
|
||||
}
|
||||
if !f.Anonymous {
|
||||
println("BUG: S1 is not anonymous");
|
||||
return;
|
||||
println("BUG: S1 is not anonymous")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -38,11 +38,11 @@ func main() {
|
||||
// meaning that reflect data for v0, v1 didn't get confused.
|
||||
|
||||
// path is full (rooted) path name. check suffix for gc, prefix for gccgo
|
||||
if s := reflect.Typeof(v0).PkgPath(); !strings.HasSuffix(s, "/bug0") && !strings.HasPrefix(s, "bug0") {
|
||||
if s := reflect.TypeOf(v0).PkgPath(); !strings.HasSuffix(s, "/bug0") && !strings.HasPrefix(s, "bug0") {
|
||||
println("bad v0 path", len(s), s)
|
||||
panic("fail")
|
||||
}
|
||||
if s := reflect.Typeof(v1).PkgPath(); !strings.HasSuffix(s, "/bug1") && !strings.HasPrefix(s, "bug1") {
|
||||
if s := reflect.TypeOf(v1).PkgPath(); !strings.HasSuffix(s, "/bug1") && !strings.HasPrefix(s, "bug1") {
|
||||
println("bad v1 path", s)
|
||||
panic("fail")
|
||||
}
|
||||
|
@ -46,34 +46,34 @@ func main() {
|
||||
x.t = add("abc", "def")
|
||||
x.u = 1
|
||||
x.v = 2
|
||||
x.w = 1<<28
|
||||
x.x = 2<<28
|
||||
x.w = 1 << 28
|
||||
x.x = 2 << 28
|
||||
x.y = 0x12345678
|
||||
x.z = x.y
|
||||
|
||||
// check mem and string
|
||||
v := reflect.NewValue(x)
|
||||
i := v.(*reflect.StructValue).Field(0)
|
||||
j := v.(*reflect.StructValue).Field(1)
|
||||
v := reflect.ValueOf(x)
|
||||
i := v.Field(0)
|
||||
j := v.Field(1)
|
||||
assert(i.Interface() == j.Interface())
|
||||
|
||||
s := v.(*reflect.StructValue).Field(2)
|
||||
t := v.(*reflect.StructValue).Field(3)
|
||||
s := v.Field(2)
|
||||
t := v.Field(3)
|
||||
assert(s.Interface() == t.Interface())
|
||||
|
||||
// make sure different values are different.
|
||||
// make sure whole word is being compared,
|
||||
// not just a single byte.
|
||||
i = v.(*reflect.StructValue).Field(4)
|
||||
j = v.(*reflect.StructValue).Field(5)
|
||||
i = v.Field(4)
|
||||
j = v.Field(5)
|
||||
assert(i.Interface() != j.Interface())
|
||||
|
||||
i = v.(*reflect.StructValue).Field(6)
|
||||
j = v.(*reflect.StructValue).Field(7)
|
||||
i = v.Field(6)
|
||||
j = v.Field(7)
|
||||
assert(i.Interface() != j.Interface())
|
||||
|
||||
i = v.(*reflect.StructValue).Field(8)
|
||||
j = v.(*reflect.StructValue).Field(9)
|
||||
i = v.Field(8)
|
||||
j = v.Field(9)
|
||||
assert(i.Interface() == j.Interface())
|
||||
}
|
||||
|
||||
|
@ -25,9 +25,9 @@ func main() {
|
||||
println(c)
|
||||
|
||||
var a interface{}
|
||||
switch c := reflect.NewValue(a).(type) {
|
||||
case *reflect.ComplexValue:
|
||||
v := c.Get()
|
||||
switch c := reflect.ValueOf(a); c.Kind() {
|
||||
case reflect.Complex64, reflect.Complex128:
|
||||
v := c.Complex()
|
||||
_, _ = complex128(v), true
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
f618e5e0991d
|
||||
aea0ba6e5935
|
||||
|
||||
The first line of this file holds the Mercurial revision number of the
|
||||
last merge done from the master library sources.
|
||||
|
@ -248,7 +248,8 @@ toolexeclibgogo_DATA = \
|
||||
go/printer.gox \
|
||||
go/scanner.gox \
|
||||
go/token.gox \
|
||||
go/typechecker.gox
|
||||
go/typechecker.gox \
|
||||
go/types.gox
|
||||
|
||||
toolexeclibgohashdir = $(toolexeclibgodir)/hash
|
||||
|
||||
@ -262,14 +263,19 @@ toolexeclibgohttpdir = $(toolexeclibgodir)/http
|
||||
|
||||
toolexeclibgohttp_DATA = \
|
||||
http/cgi.gox \
|
||||
http/fcgi.gox \
|
||||
http/httptest.gox \
|
||||
http/pprof.gox
|
||||
http/pprof.gox \
|
||||
http/spdy.gox
|
||||
|
||||
toolexeclibgoimagedir = $(toolexeclibgodir)/image
|
||||
|
||||
toolexeclibgoimage_DATA = \
|
||||
image/gif.gox \
|
||||
image/jpeg.gox \
|
||||
image/png.gox
|
||||
image/png.gox \
|
||||
image/tiff.gox \
|
||||
image/ycbcr.gox
|
||||
|
||||
toolexeclibgoindexdir = $(toolexeclibgodir)/index
|
||||
|
||||
@ -303,6 +309,7 @@ endif
|
||||
|
||||
toolexeclibgoos_DATA = \
|
||||
$(os_inotify_gox) \
|
||||
os/user.gox \
|
||||
os/signal.gox
|
||||
|
||||
toolexeclibgopathdir = $(toolexeclibgodir)/path
|
||||
@ -404,6 +411,7 @@ runtime_files = \
|
||||
runtime/go-send-nb-big.c \
|
||||
runtime/go-send-nb-small.c \
|
||||
runtime/go-send-small.c \
|
||||
runtime/go-setenv.c \
|
||||
runtime/go-signal.c \
|
||||
runtime/go-strcmp.c \
|
||||
runtime/go-string-to-byte-array.c \
|
||||
@ -560,6 +568,7 @@ go_http_files = \
|
||||
go/http/persist.go \
|
||||
go/http/request.go \
|
||||
go/http/response.go \
|
||||
go/http/reverseproxy.go \
|
||||
go/http/server.go \
|
||||
go/http/status.go \
|
||||
go/http/transfer.go \
|
||||
@ -656,8 +665,17 @@ go_net_newpollserver_file = go/net/newpollserver.go
|
||||
endif # !LIBGO_IS_LINUX
|
||||
endif # !LIBGO_IS_RTEMS
|
||||
|
||||
if LIBGO_IS_LINUX
|
||||
go_net_cgo_file = go/net/cgo_linux.go
|
||||
go_net_sock_file = go/net/sock_linux.go
|
||||
else
|
||||
go_net_cgo_file = go/net/cgo_bsd.go
|
||||
go_net_sock_file = go/net/sock_bsd.go
|
||||
endif
|
||||
|
||||
go_net_files = \
|
||||
go/net/cgo_stub.go \
|
||||
go/net/cgo_unix.go \
|
||||
$(go_net_cgo_file) \
|
||||
go/net/dial.go \
|
||||
go/net/dnsclient.go \
|
||||
go/net/dnsconfig.go \
|
||||
@ -676,6 +694,7 @@ go_net_files = \
|
||||
go/net/pipe.go \
|
||||
go/net/port.go \
|
||||
go/net/sock.go \
|
||||
$(go_net_sock_file) \
|
||||
go/net/tcpsock.go \
|
||||
go/net/udpsock.go \
|
||||
go/net/unixsock.go
|
||||
@ -1002,7 +1021,6 @@ go_crypto_subtle_files = \
|
||||
go/crypto/subtle/constant_time.go
|
||||
go_crypto_tls_files = \
|
||||
go/crypto/tls/alert.go \
|
||||
go/crypto/tls/ca_set.go \
|
||||
go/crypto/tls/cipher_suites.go \
|
||||
go/crypto/tls/common.go \
|
||||
go/crypto/tls/conn.go \
|
||||
@ -1015,6 +1033,8 @@ go_crypto_tls_files = \
|
||||
go_crypto_twofish_files = \
|
||||
go/crypto/twofish/twofish.go
|
||||
go_crypto_x509_files = \
|
||||
go/crypto/x509/cert_pool.go \
|
||||
go/crypto/x509/verify.go \
|
||||
go/crypto/x509/x509.go
|
||||
go_crypto_xtea_files = \
|
||||
go/crypto/xtea/block.go \
|
||||
@ -1130,6 +1150,12 @@ go_go_typechecker_files = \
|
||||
go/go/typechecker/type.go \
|
||||
go/go/typechecker/typechecker.go \
|
||||
go/go/typechecker/universe.go
|
||||
go_go_types_files = \
|
||||
go/go/types/const.go \
|
||||
go/go/types/exportdata.go \
|
||||
go/go/types/gcimporter.go \
|
||||
go/go/types/types.go \
|
||||
go/go/types/universe.go
|
||||
|
||||
go_hash_adler32_files = \
|
||||
go/hash/adler32/adler32.go
|
||||
@ -1143,21 +1169,39 @@ go_hash_fnv_files = \
|
||||
go_http_cgi_files = \
|
||||
go/http/cgi/child.go \
|
||||
go/http/cgi/host.go
|
||||
go_http_fcgi_files = \
|
||||
go/http/fcgi/child.go \
|
||||
go/http/fcgi/fcgi.go
|
||||
go_http_httptest_files = \
|
||||
go/http/httptest/recorder.go \
|
||||
go/http/httptest/server.go
|
||||
go_http_pprof_files = \
|
||||
go/http/pprof/pprof.go
|
||||
go_http_spdy_files = \
|
||||
go/http/spdy/protocol.go
|
||||
|
||||
go_image_gif_files = \
|
||||
go/image/gif/reader.go
|
||||
|
||||
go_image_jpeg_files = \
|
||||
go/image/jpeg/fdct.go \
|
||||
go/image/jpeg/huffman.go \
|
||||
go/image/jpeg/idct.go \
|
||||
go/image/jpeg/reader.go
|
||||
go/image/jpeg/reader.go \
|
||||
go/image/jpeg/writer.go
|
||||
|
||||
go_image_png_files = \
|
||||
go/image/png/reader.go \
|
||||
go/image/png/writer.go
|
||||
|
||||
go_image_tiff_files = \
|
||||
go/image/tiff/buffer.go \
|
||||
go/image/tiff/consts.go \
|
||||
go/image/tiff/reader.go
|
||||
|
||||
go_image_ycbcr_files = \
|
||||
go/image/ycbcr/ycbcr.go
|
||||
|
||||
go_index_suffixarray_files = \
|
||||
go/index/suffixarray/qsufsort.go \
|
||||
go/index/suffixarray/suffixarray.go
|
||||
@ -1167,6 +1211,7 @@ go_io_ioutil_files = \
|
||||
go/io/ioutil/tempfile.go
|
||||
|
||||
go_mime_multipart_files = \
|
||||
go/mime/multipart/formdata.go \
|
||||
go/mime/multipart/multipart.go
|
||||
|
||||
go_net_dict_files = \
|
||||
@ -1182,6 +1227,10 @@ go_net_textproto_files = \
|
||||
go_os_inotify_files = \
|
||||
go/os/inotify/inotify_linux.go
|
||||
|
||||
go_os_user_files = \
|
||||
go/os/user/user.go \
|
||||
go/os/user/lookup_unix.go
|
||||
|
||||
go_os_signal_files = \
|
||||
go/os/signal/signal.go \
|
||||
unix.go
|
||||
@ -1485,21 +1534,28 @@ libgo_go_objs = \
|
||||
go/scanner.lo \
|
||||
go/token.lo \
|
||||
go/typechecker.lo \
|
||||
go/types.lo \
|
||||
hash/adler32.lo \
|
||||
hash/crc32.lo \
|
||||
hash/crc64.lo \
|
||||
hash/fnv.lo \
|
||||
http/cgi.lo \
|
||||
http/fcgi.lo \
|
||||
http/httptest.lo \
|
||||
http/pprof.lo \
|
||||
http/spdy.lo \
|
||||
image/gif.lo \
|
||||
image/jpeg.lo \
|
||||
image/png.lo \
|
||||
image/tiff.lo \
|
||||
image/ycbcr.lo \
|
||||
index/suffixarray.lo \
|
||||
io/ioutil.lo \
|
||||
mime/multipart.lo \
|
||||
net/dict.lo \
|
||||
net/textproto.lo \
|
||||
$(os_lib_inotify_lo) \
|
||||
os/user.lo \
|
||||
os/signal.lo \
|
||||
path/filepath.lo \
|
||||
rpc/jsonrpc.lo \
|
||||
@ -1711,11 +1767,12 @@ html/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: html/check
|
||||
|
||||
http/http.lo: $(go_http_files) bufio.gox bytes.gox container/vector.gox \
|
||||
crypto/rand.gox crypto/tls.gox encoding/base64.gox fmt.gox \
|
||||
io.gox io/ioutil.gox log.gox mime.gox mime/multipart.gox \
|
||||
net.gox net/textproto.gox os.gox path.gox path/filepath.gox \
|
||||
sort.gox strconv.gox strings.gox sync.gox time.gox utf8.gox
|
||||
http/http.lo: $(go_http_files) bufio.gox bytes.gox compress/gzip.gox \
|
||||
container/vector.gox crypto/rand.gox crypto/tls.gox \
|
||||
encoding/base64.gox fmt.gox io.gox io/ioutil.gox log.gox \
|
||||
mime.gox mime/multipart.gox net.gox net/textproto.gox os.gox \
|
||||
path.gox path/filepath.gox sort.gox strconv.gox strings.gox \
|
||||
sync.gox time.gox utf8.gox
|
||||
$(BUILDPACKAGE)
|
||||
http/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
@ -1755,7 +1812,7 @@ math/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: math/check
|
||||
|
||||
mime/mime.lo: $(go_mime_files) bufio.gox bytes.gox os.gox strings.gox \
|
||||
mime/mime.lo: $(go_mime_files) bufio.gox bytes.gox fmt.gox os.gox strings.gox \
|
||||
sync.gox unicode.gox
|
||||
$(BUILDPACKAGE)
|
||||
mime/check: $(CHECK_DEPS)
|
||||
@ -1763,8 +1820,8 @@ mime/check: $(CHECK_DEPS)
|
||||
.PHONY: mime/check
|
||||
|
||||
net/net.lo: $(go_net_files) bytes.gox fmt.gox io.gox os.gox rand.gox \
|
||||
reflect.gox strconv.gox strings.gox sync.gox syscall.gox \
|
||||
time.gox
|
||||
reflect.gox sort.gox strconv.gox strings.gox sync.gox \
|
||||
syscall.gox time.gox
|
||||
$(BUILDPACKAGE)
|
||||
net/check: $(CHECK_DEPS)
|
||||
@$(CHECK_ON_REQUEST)
|
||||
@ -1945,8 +2002,8 @@ xml/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: xml/check
|
||||
|
||||
archive/tar.lo: $(go_archive_tar_files) bytes.gox io.gox os.gox strconv.gox \
|
||||
strings.gox
|
||||
archive/tar.lo: $(go_archive_tar_files) bytes.gox io.gox io/ioutil.gox os.gox \
|
||||
strconv.gox strings.gox
|
||||
$(BUILDPACKAGE)
|
||||
archive/tar/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) archive/tar
|
||||
@ -2148,8 +2205,7 @@ crypto/ripemd160/check: $(CHECK_DEPS)
|
||||
.PHONY: crypto/ripemd160/check
|
||||
|
||||
crypto/rsa.lo: $(go_crypto_rsa_files) big.gox crypto.gox crypto/sha1.gox \
|
||||
crypto/subtle.gox encoding/hex.gox hash.gox io.gox os.gox \
|
||||
sync.gox
|
||||
crypto/subtle.gox encoding/hex.gox hash.gox io.gox os.gox
|
||||
$(BUILDPACKAGE)
|
||||
crypto/rsa/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) crypto/rsa
|
||||
@ -2184,13 +2240,13 @@ crypto/subtle/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: crypto/subtle/check
|
||||
|
||||
crypto/tls.lo: $(go_crypto_tls_files) big.gox bufio.gox bytes.gox \
|
||||
container/list.gox crypto.gox crypto/aes.gox crypto/cipher.gox \
|
||||
crypto/elliptic.gox crypto/hmac.gox crypto/md5.gox \
|
||||
crypto/rc4.gox crypto/rand.gox crypto/rsa.gox crypto/sha1.gox \
|
||||
crypto/subtle.gox crypto/rsa.gox crypto/sha1.gox \
|
||||
crypto/x509.gox encoding/pem.gox fmt.gox hash.gox io.gox \
|
||||
io/ioutil.gox net.gox os.gox strings.gox sync.gox time.gox
|
||||
crypto/tls.lo: $(go_crypto_tls_files) big.gox bytes.gox crypto.gox \
|
||||
crypto/aes.gox crypto/cipher.gox crypto/elliptic.gox \
|
||||
crypto/hmac.gox crypto/md5.gox crypto/rand.gox crypto/rc4.gox \
|
||||
crypto/rsa.gox crypto/sha1.gox crypto/subtle.gox \
|
||||
crypto/x509.gox encoding/pem.gox hash.gox io.gox \
|
||||
io/ioutil.gox net.gox os.gox strconv.gox strings.gox sync.gox \
|
||||
time.gox
|
||||
$(BUILDPACKAGE)
|
||||
crypto/tls/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) crypto/tls
|
||||
@ -2204,9 +2260,10 @@ crypto/twofish/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: crypto/twofish/check
|
||||
|
||||
crypto/x509.lo: $(go_crypto_x509_files) asn1.gox big.gox container/vector.gox \
|
||||
crypto.gox crypto/rsa.gox crypto/sha1.gox hash.gox os.gox \
|
||||
strings.gox time.gox
|
||||
crypto/x509.lo: $(go_crypto_x509_files) asn1.gox big.gox bytes.gox \
|
||||
container/vector.gox crypto.gox crypto/rsa.gox \
|
||||
crypto/sha1.gox encoding/pem.gox hash.gox os.gox strings.gox \
|
||||
time.gox
|
||||
$(BUILDPACKAGE)
|
||||
crypto/x509/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) crypto/x509
|
||||
@ -2220,9 +2277,8 @@ crypto/xtea/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: crypto/xtea/check
|
||||
|
||||
crypto/openpgp/armor.lo: $(go_crypto_openpgp_armor_files) bytes.gox \
|
||||
crypto/openpgp/error.gox encoding/base64.gox \
|
||||
encoding/line.gox io.gox os.gox
|
||||
crypto/openpgp/armor.lo: $(go_crypto_openpgp_armor_files) bufio.gox bytes.gox \
|
||||
crypto/openpgp/error.gox encoding/base64.gox io.gox os.gox
|
||||
$(BUILDPACKAGE)
|
||||
crypto/openpgp/armor/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) crypto/openpgp/armor
|
||||
@ -2374,7 +2430,7 @@ exp/datafmt/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: exp/datafmt/check
|
||||
|
||||
exp/draw.lo: $(go_exp_draw_files) image.gox os.gox
|
||||
exp/draw.lo: $(go_exp_draw_files) image.gox image/ycbcr.gox os.gox
|
||||
$(BUILDPACKAGE)
|
||||
exp/draw/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) exp/draw
|
||||
@ -2448,6 +2504,15 @@ go/typechecker/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: go/typechecker/check
|
||||
|
||||
go/types.lo: $(go_go_types_files) big.gox bufio.gox fmt.gox go/ast.gox \
|
||||
go/token.gox io.gox os.gox path/filepath.gox runtime.gox \
|
||||
scanner.gox strconv.gox strings.gox
|
||||
$(BUILDPACKAGE)
|
||||
go/types/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) go/types
|
||||
@$(CHECK)
|
||||
.PHONY: go/types/check
|
||||
|
||||
hash/adler32.lo: $(go_hash_adler32_files) hash.gox os.gox
|
||||
$(BUILDPACKAGE)
|
||||
hash/adler32/check: $(CHECK_DEPS)
|
||||
@ -2476,15 +2541,25 @@ hash/fnv/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: hash/fnv/check
|
||||
|
||||
http/cgi.lo: $(go_http_cgi_files) bufio.gox bytes.gox encoding/line.gox \
|
||||
exec.gox fmt.gox http.gox io.gox io/ioutil.gox log.gox \
|
||||
os.gox path/filepath.gox regexp.gox strconv.gox strings.gox
|
||||
http/cgi.lo: $(go_http_cgi_files) bufio.gox bytes.gox crypto/tls.gox \
|
||||
exec.gox fmt.gox http.gox net.gox io.gox io/ioutil.gox \
|
||||
log.gox os.gox path/filepath.gox regexp.gox strconv.gox \
|
||||
strings.gox
|
||||
$(BUILDPACKAGE)
|
||||
http/cgi/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) http/cgi
|
||||
@$(CHECK)
|
||||
.PHONY: http/cgi/check
|
||||
|
||||
http/fcgi.lo: $(go_http_fcgi_files) bufio.gox bytes.gox encoding/binary.gox \
|
||||
fmt.gox http.gox http/cgi.gox io.gox net.gox os.gox sync.gox \
|
||||
time.gox
|
||||
$(BUILDPACKAGE)
|
||||
http/fcgi/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) http/fcgi
|
||||
@$(CHECK)
|
||||
.PHONY: http/fcgi/check
|
||||
|
||||
http/httptest.lo: $(go_http_httptest_files) bytes.gox crypto/rand.gox \
|
||||
crypto/tls.gox fmt.gox http.gox net.gox os.gox time.gox
|
||||
$(BUILDPACKAGE)
|
||||
@ -2493,15 +2568,33 @@ http/httptest/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: http/httptest/check
|
||||
|
||||
http/pprof.lo: $(go_http_pprof_files) bufio.gox fmt.gox http.gox os.gox \
|
||||
runtime.gox runtime/pprof.gox strconv.gox strings.gox
|
||||
http/pprof.lo: $(go_http_pprof_files) bufio.gox bytes.gox fmt.gox http.gox \
|
||||
os.gox runtime.gox runtime/pprof.gox strconv.gox strings.gox
|
||||
$(BUILDPACKAGE)
|
||||
http/pprof/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) http/pprof
|
||||
@$(CHECK)
|
||||
.PHONY: http/pprof/check
|
||||
|
||||
image/jpeg.lo: $(go_image_jpeg_files) bufio.gox image.gox io.gox os.gox
|
||||
http/spdy.lo: $(go_http_spdy_files) bytes.gox compress/zlib.gox \
|
||||
encoding/binary.gox http.gox io.gox os.gox strconv.gox \
|
||||
strings.gox sync.gox
|
||||
$(BUILDPACKAGE)
|
||||
http/spdy/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) http/spdy
|
||||
@$(CHECK)
|
||||
.PHONY: http/spdy/check
|
||||
|
||||
image/gif.lo: $(go_image_gif_files) bufio.gox compress/lzw.gox fmt.gox \
|
||||
image.gox io.gox os.gox
|
||||
$(BUILDPACKAGE)
|
||||
image/gif/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) image/gif
|
||||
@$(CHECK)
|
||||
.PHONY: image/gif/check
|
||||
|
||||
image/jpeg.lo: $(go_image_jpeg_files) bufio.gox image.gox image/ycbcr.gox \
|
||||
io.gox os.gox
|
||||
$(BUILDPACKAGE)
|
||||
image/jpeg/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) image/jpeg
|
||||
@ -2516,6 +2609,21 @@ image/png/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: image/png/check
|
||||
|
||||
image/tiff.lo: $(go_image_tiff_files) compress/lzw.gox compress/zlib.gox \
|
||||
encoding/binary.gox image.gox io.gox io/ioutil.gox os.gox
|
||||
$(BUILDPACKAGE)
|
||||
image/tiff/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) image/tiff
|
||||
@$(CHECK)
|
||||
.PHONY: image/tiff/check
|
||||
|
||||
image/ycbcr.lo: $(go_image_ycbcr_files) image.gox
|
||||
$(BUILDPACKAGE)
|
||||
image/ycbcr/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) image/ycbcr
|
||||
@$(CHECK)
|
||||
.PHONY: image/ycbcr/check
|
||||
|
||||
index/suffixarray.lo: $(go_index_suffixarray_files) bytes.gox regexp.gox \
|
||||
sort.gox
|
||||
$(BUILDPACKAGE)
|
||||
@ -2532,8 +2640,9 @@ io/ioutil/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: io/ioutil/check
|
||||
|
||||
mime/multipart.lo: $(go_mime_multipart_files) bufio.gox bytes.gox io.gox \
|
||||
mime.gox net/textproto.gox os.gox regexp.gox strings.gox
|
||||
mime/multipart.lo: $(go_mime_multipart_files) bufio.gox bytes.gox fmt.gox \
|
||||
io.gox io/ioutil.gox mime.gox net/textproto.gox os.gox \
|
||||
regexp.gox
|
||||
$(BUILDPACKAGE)
|
||||
mime/multipart/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) mime/multipart
|
||||
@ -2560,6 +2669,14 @@ os/inotify/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: os/inotify/check
|
||||
|
||||
os/user.lo: $(go_os_user_files) fmt.gox os.gox runtime.gox strconv.gox \
|
||||
strings.gox syscall.gox
|
||||
$(BUILDPACKAGE)
|
||||
os/user/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) os/user
|
||||
@$(CHECK)
|
||||
.PHONY: os/user/check
|
||||
|
||||
os/signal.lo: $(go_os_signal_files) runtime.gox strconv.gox
|
||||
$(BUILDPACKAGE)
|
||||
os/signal/check: $(CHECK_DEPS)
|
||||
@ -2886,6 +3003,8 @@ go/token.gox: go/token.lo
|
||||
$(BUILDGOX)
|
||||
go/typechecker.gox: go/typechecker.lo
|
||||
$(BUILDGOX)
|
||||
go/types.gox: go/types.lo
|
||||
$(BUILDGOX)
|
||||
|
||||
hash/adler32.gox: hash/adler32.lo
|
||||
$(BUILDGOX)
|
||||
@ -2898,15 +3017,25 @@ hash/fnv.gox: hash/fnv.lo
|
||||
|
||||
http/cgi.gox: http/cgi.lo
|
||||
$(BUILDGOX)
|
||||
http/fcgi.gox: http/fcgi.lo
|
||||
$(BUILDGOX)
|
||||
http/httptest.gox: http/httptest.lo
|
||||
$(BUILDGOX)
|
||||
http/pprof.gox: http/pprof.lo
|
||||
$(BUILDGOX)
|
||||
http/spdy.gox: http/spdy.lo
|
||||
$(BUILDGOX)
|
||||
|
||||
image/gif.gox: image/gif.lo
|
||||
$(BUILDGOX)
|
||||
image/jpeg.gox: image/jpeg.lo
|
||||
$(BUILDGOX)
|
||||
image/png.gox: image/png.lo
|
||||
$(BUILDGOX)
|
||||
image/tiff.gox: image/tiff.lo
|
||||
$(BUILDGOX)
|
||||
image/ycbcr.gox: image/ycbcr.lo
|
||||
$(BUILDGOX)
|
||||
|
||||
index/suffixarray.gox: index/suffixarray.lo
|
||||
$(BUILDGOX)
|
||||
@ -2924,6 +3053,8 @@ net/textproto.gox: net/textproto.lo
|
||||
|
||||
os/inotify.gox: os/inotify.lo
|
||||
$(BUILDGOX)
|
||||
os/user.gox: os/user.lo
|
||||
$(BUILDGOX)
|
||||
os/signal.gox: os/signal.lo
|
||||
$(BUILDGOX)
|
||||
|
||||
@ -3054,22 +3185,30 @@ TEST_PACKAGES = \
|
||||
exp/datafmt/check \
|
||||
exp/draw/check \
|
||||
exp/eval/check \
|
||||
go/ast/check \
|
||||
go/parser/check \
|
||||
go/printer/check \
|
||||
go/scanner/check \
|
||||
go/token/check \
|
||||
go/typechecker/check \
|
||||
$(go_types_check_omitted_since_it_calls_6g) \
|
||||
hash/adler32/check \
|
||||
hash/crc32/check \
|
||||
hash/crc64/check \
|
||||
hash/fnv/check \
|
||||
http/cgi/check \
|
||||
http/fcgi/check \
|
||||
http/spdy/check \
|
||||
image/jpeg/check \
|
||||
image/png/check \
|
||||
image/tiff/check \
|
||||
image/ycbcr/check \
|
||||
index/suffixarray/check \
|
||||
io/ioutil/check \
|
||||
mime/multipart/check \
|
||||
net/textproto/check \
|
||||
$(os_inotify_check) \
|
||||
os/user/check \
|
||||
os/signal/check \
|
||||
path/filepath/check \
|
||||
rpc/jsonrpc/check \
|
||||
|
@ -155,15 +155,17 @@ am__DEPENDENCIES_2 = asn1/asn1.lo big/big.lo bufio/bufio.lo \
|
||||
encoding/binary.lo encoding/git85.lo encoding/hex.lo \
|
||||
encoding/line.lo encoding/pem.lo exp/datafmt.lo exp/draw.lo \
|
||||
exp/eval.lo go/ast.lo go/doc.lo go/parser.lo go/printer.lo \
|
||||
go/scanner.lo go/token.lo go/typechecker.lo hash/adler32.lo \
|
||||
hash/crc32.lo hash/crc64.lo hash/fnv.lo http/cgi.lo \
|
||||
http/httptest.lo http/pprof.lo image/jpeg.lo image/png.lo \
|
||||
index/suffixarray.lo io/ioutil.lo mime/multipart.lo \
|
||||
net/dict.lo net/textproto.lo $(am__DEPENDENCIES_1) \
|
||||
os/signal.lo path/filepath.lo rpc/jsonrpc.lo runtime/debug.lo \
|
||||
runtime/pprof.lo sync/atomic.lo sync/atomic_c.lo \
|
||||
syscalls/syscall.lo syscalls/errno.lo testing/testing.lo \
|
||||
testing/iotest.lo testing/quick.lo testing/script.lo
|
||||
go/scanner.lo go/token.lo go/typechecker.lo go/types.lo \
|
||||
hash/adler32.lo hash/crc32.lo hash/crc64.lo hash/fnv.lo \
|
||||
http/cgi.lo http/fcgi.lo http/httptest.lo http/pprof.lo \
|
||||
http/spdy.lo image/gif.lo image/jpeg.lo image/png.lo \
|
||||
image/tiff.lo image/ycbcr.lo index/suffixarray.lo io/ioutil.lo \
|
||||
mime/multipart.lo net/dict.lo net/textproto.lo \
|
||||
$(am__DEPENDENCIES_1) os/user.lo os/signal.lo path/filepath.lo \
|
||||
rpc/jsonrpc.lo runtime/debug.lo runtime/pprof.lo \
|
||||
sync/atomic.lo sync/atomic_c.lo syscalls/syscall.lo \
|
||||
syscalls/errno.lo testing/testing.lo testing/iotest.lo \
|
||||
testing/quick.lo testing/script.lo
|
||||
libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
|
||||
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
|
||||
$(am__DEPENDENCIES_1)
|
||||
@ -196,7 +198,7 @@ am__libgo_la_SOURCES_DIST = runtime/go-append.c runtime/go-assert.c \
|
||||
runtime/go-select.c runtime/go-semacquire.c \
|
||||
runtime/go-send-big.c runtime/go-send-nb-big.c \
|
||||
runtime/go-send-nb-small.c runtime/go-send-small.c \
|
||||
runtime/go-signal.c runtime/go-strcmp.c \
|
||||
runtime/go-setenv.c runtime/go-signal.c runtime/go-strcmp.c \
|
||||
runtime/go-string-to-byte-array.c \
|
||||
runtime/go-string-to-int-array.c runtime/go-strplus.c \
|
||||
runtime/go-strslice.c runtime/go-trampoline.c \
|
||||
@ -233,7 +235,7 @@ am__objects_3 = go-append.lo go-assert.lo go-assert-interface.lo \
|
||||
go-reflect-chan.lo go-reflect-map.lo go-rune.lo \
|
||||
go-runtime-error.lo go-sched.lo go-select.lo go-semacquire.lo \
|
||||
go-send-big.lo go-send-nb-big.lo go-send-nb-small.lo \
|
||||
go-send-small.lo go-signal.lo go-strcmp.lo \
|
||||
go-send-small.lo go-setenv.lo go-signal.lo go-strcmp.lo \
|
||||
go-string-to-byte-array.lo go-string-to-int-array.lo \
|
||||
go-strplus.lo go-strslice.lo go-trampoline.lo go-type-eface.lo \
|
||||
go-type-error.lo go-type-identity.lo go-type-interface.lo \
|
||||
@ -689,7 +691,8 @@ toolexeclibgogo_DATA = \
|
||||
go/printer.gox \
|
||||
go/scanner.gox \
|
||||
go/token.gox \
|
||||
go/typechecker.gox
|
||||
go/typechecker.gox \
|
||||
go/types.gox
|
||||
|
||||
toolexeclibgohashdir = $(toolexeclibgodir)/hash
|
||||
toolexeclibgohash_DATA = \
|
||||
@ -701,13 +704,18 @@ toolexeclibgohash_DATA = \
|
||||
toolexeclibgohttpdir = $(toolexeclibgodir)/http
|
||||
toolexeclibgohttp_DATA = \
|
||||
http/cgi.gox \
|
||||
http/fcgi.gox \
|
||||
http/httptest.gox \
|
||||
http/pprof.gox
|
||||
http/pprof.gox \
|
||||
http/spdy.gox
|
||||
|
||||
toolexeclibgoimagedir = $(toolexeclibgodir)/image
|
||||
toolexeclibgoimage_DATA = \
|
||||
image/gif.gox \
|
||||
image/jpeg.gox \
|
||||
image/png.gox
|
||||
image/png.gox \
|
||||
image/tiff.gox \
|
||||
image/ycbcr.gox
|
||||
|
||||
toolexeclibgoindexdir = $(toolexeclibgodir)/index
|
||||
toolexeclibgoindex_DATA = \
|
||||
@ -733,6 +741,7 @@ toolexeclibgoosdir = $(toolexeclibgodir)/os
|
||||
@LIBGO_IS_LINUX_TRUE@os_inotify_gox =
|
||||
toolexeclibgoos_DATA = \
|
||||
$(os_inotify_gox) \
|
||||
os/user.gox \
|
||||
os/signal.gox
|
||||
|
||||
toolexeclibgopathdir = $(toolexeclibgodir)/path
|
||||
@ -821,6 +830,7 @@ runtime_files = \
|
||||
runtime/go-send-nb-big.c \
|
||||
runtime/go-send-nb-small.c \
|
||||
runtime/go-send-small.c \
|
||||
runtime/go-setenv.c \
|
||||
runtime/go-signal.c \
|
||||
runtime/go-strcmp.c \
|
||||
runtime/go-string-to-byte-array.c \
|
||||
@ -952,6 +962,7 @@ go_http_files = \
|
||||
go/http/persist.go \
|
||||
go/http/request.go \
|
||||
go/http/response.go \
|
||||
go/http/reverseproxy.go \
|
||||
go/http/server.go \
|
||||
go/http/status.go \
|
||||
go/http/transfer.go \
|
||||
@ -1041,8 +1052,13 @@ go_mime_files = \
|
||||
@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_RTEMS_FALSE@go_net_newpollserver_file = go/net/newpollserver.go
|
||||
@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_RTEMS_FALSE@go_net_newpollserver_file = go/net/newpollserver.go
|
||||
@LIBGO_IS_RTEMS_TRUE@go_net_newpollserver_file = go/net/newpollserver_rtems.go
|
||||
@LIBGO_IS_LINUX_FALSE@go_net_cgo_file = go/net/cgo_bsd.go
|
||||
@LIBGO_IS_LINUX_TRUE@go_net_cgo_file = go/net/cgo_linux.go
|
||||
@LIBGO_IS_LINUX_FALSE@go_net_sock_file = go/net/sock_bsd.go
|
||||
@LIBGO_IS_LINUX_TRUE@go_net_sock_file = go/net/sock_linux.go
|
||||
go_net_files = \
|
||||
go/net/cgo_stub.go \
|
||||
go/net/cgo_unix.go \
|
||||
$(go_net_cgo_file) \
|
||||
go/net/dial.go \
|
||||
go/net/dnsclient.go \
|
||||
go/net/dnsconfig.go \
|
||||
@ -1061,6 +1077,7 @@ go_net_files = \
|
||||
go/net/pipe.go \
|
||||
go/net/port.go \
|
||||
go/net/sock.go \
|
||||
$(go_net_sock_file) \
|
||||
go/net/tcpsock.go \
|
||||
go/net/udpsock.go \
|
||||
go/net/unixsock.go
|
||||
@ -1365,7 +1382,6 @@ go_crypto_subtle_files = \
|
||||
|
||||
go_crypto_tls_files = \
|
||||
go/crypto/tls/alert.go \
|
||||
go/crypto/tls/ca_set.go \
|
||||
go/crypto/tls/cipher_suites.go \
|
||||
go/crypto/tls/common.go \
|
||||
go/crypto/tls/conn.go \
|
||||
@ -1380,6 +1396,8 @@ go_crypto_twofish_files = \
|
||||
go/crypto/twofish/twofish.go
|
||||
|
||||
go_crypto_x509_files = \
|
||||
go/crypto/x509/cert_pool.go \
|
||||
go/crypto/x509/verify.go \
|
||||
go/crypto/x509/x509.go
|
||||
|
||||
go_crypto_xtea_files = \
|
||||
@ -1519,6 +1537,13 @@ go_go_typechecker_files = \
|
||||
go/go/typechecker/typechecker.go \
|
||||
go/go/typechecker/universe.go
|
||||
|
||||
go_go_types_files = \
|
||||
go/go/types/const.go \
|
||||
go/go/types/exportdata.go \
|
||||
go/go/types/gcimporter.go \
|
||||
go/go/types/types.go \
|
||||
go/go/types/universe.go
|
||||
|
||||
go_hash_adler32_files = \
|
||||
go/hash/adler32/adler32.go
|
||||
|
||||
@ -1535,6 +1560,10 @@ go_http_cgi_files = \
|
||||
go/http/cgi/child.go \
|
||||
go/http/cgi/host.go
|
||||
|
||||
go_http_fcgi_files = \
|
||||
go/http/fcgi/child.go \
|
||||
go/http/fcgi/fcgi.go
|
||||
|
||||
go_http_httptest_files = \
|
||||
go/http/httptest/recorder.go \
|
||||
go/http/httptest/server.go
|
||||
@ -1542,15 +1571,31 @@ go_http_httptest_files = \
|
||||
go_http_pprof_files = \
|
||||
go/http/pprof/pprof.go
|
||||
|
||||
go_http_spdy_files = \
|
||||
go/http/spdy/protocol.go
|
||||
|
||||
go_image_gif_files = \
|
||||
go/image/gif/reader.go
|
||||
|
||||
go_image_jpeg_files = \
|
||||
go/image/jpeg/fdct.go \
|
||||
go/image/jpeg/huffman.go \
|
||||
go/image/jpeg/idct.go \
|
||||
go/image/jpeg/reader.go
|
||||
go/image/jpeg/reader.go \
|
||||
go/image/jpeg/writer.go
|
||||
|
||||
go_image_png_files = \
|
||||
go/image/png/reader.go \
|
||||
go/image/png/writer.go
|
||||
|
||||
go_image_tiff_files = \
|
||||
go/image/tiff/buffer.go \
|
||||
go/image/tiff/consts.go \
|
||||
go/image/tiff/reader.go
|
||||
|
||||
go_image_ycbcr_files = \
|
||||
go/image/ycbcr/ycbcr.go
|
||||
|
||||
go_index_suffixarray_files = \
|
||||
go/index/suffixarray/qsufsort.go \
|
||||
go/index/suffixarray/suffixarray.go
|
||||
@ -1560,6 +1605,7 @@ go_io_ioutil_files = \
|
||||
go/io/ioutil/tempfile.go
|
||||
|
||||
go_mime_multipart_files = \
|
||||
go/mime/multipart/formdata.go \
|
||||
go/mime/multipart/multipart.go
|
||||
|
||||
go_net_dict_files = \
|
||||
@ -1575,6 +1621,10 @@ go_net_textproto_files = \
|
||||
go_os_inotify_files = \
|
||||
go/os/inotify/inotify_linux.go
|
||||
|
||||
go_os_user_files = \
|
||||
go/os/user/user.go \
|
||||
go/os/user/lookup_unix.go
|
||||
|
||||
go_os_signal_files = \
|
||||
go/os/signal/signal.go \
|
||||
unix.go
|
||||
@ -1816,21 +1866,28 @@ libgo_go_objs = \
|
||||
go/scanner.lo \
|
||||
go/token.lo \
|
||||
go/typechecker.lo \
|
||||
go/types.lo \
|
||||
hash/adler32.lo \
|
||||
hash/crc32.lo \
|
||||
hash/crc64.lo \
|
||||
hash/fnv.lo \
|
||||
http/cgi.lo \
|
||||
http/fcgi.lo \
|
||||
http/httptest.lo \
|
||||
http/pprof.lo \
|
||||
http/spdy.lo \
|
||||
image/gif.lo \
|
||||
image/jpeg.lo \
|
||||
image/png.lo \
|
||||
image/tiff.lo \
|
||||
image/ycbcr.lo \
|
||||
index/suffixarray.lo \
|
||||
io/ioutil.lo \
|
||||
mime/multipart.lo \
|
||||
net/dict.lo \
|
||||
net/textproto.lo \
|
||||
$(os_lib_inotify_lo) \
|
||||
os/user.lo \
|
||||
os/signal.lo \
|
||||
path/filepath.lo \
|
||||
rpc/jsonrpc.lo \
|
||||
@ -2052,22 +2109,30 @@ TEST_PACKAGES = \
|
||||
exp/datafmt/check \
|
||||
exp/draw/check \
|
||||
exp/eval/check \
|
||||
go/ast/check \
|
||||
go/parser/check \
|
||||
go/printer/check \
|
||||
go/scanner/check \
|
||||
go/token/check \
|
||||
go/typechecker/check \
|
||||
$(go_types_check_omitted_since_it_calls_6g) \
|
||||
hash/adler32/check \
|
||||
hash/crc32/check \
|
||||
hash/crc64/check \
|
||||
hash/fnv/check \
|
||||
http/cgi/check \
|
||||
http/fcgi/check \
|
||||
http/spdy/check \
|
||||
image/jpeg/check \
|
||||
image/png/check \
|
||||
image/tiff/check \
|
||||
image/ycbcr/check \
|
||||
index/suffixarray/check \
|
||||
io/ioutil/check \
|
||||
mime/multipart/check \
|
||||
net/textproto/check \
|
||||
$(os_inotify_check) \
|
||||
os/user/check \
|
||||
os/signal/check \
|
||||
path/filepath/check \
|
||||
rpc/jsonrpc/check \
|
||||
@ -2270,6 +2335,7 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-send-nb-big.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-send-nb-small.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-send-small.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-setenv.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-signal.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-strcmp.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-string-to-byte-array.Plo@am__quote@
|
||||
@ -2750,6 +2816,13 @@ go-send-small.lo: runtime/go-send-small.c
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-send-small.lo `test -f 'runtime/go-send-small.c' || echo '$(srcdir)/'`runtime/go-send-small.c
|
||||
|
||||
go-setenv.lo: runtime/go-setenv.c
|
||||
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-setenv.lo -MD -MP -MF $(DEPDIR)/go-setenv.Tpo -c -o go-setenv.lo `test -f 'runtime/go-setenv.c' || echo '$(srcdir)/'`runtime/go-setenv.c
|
||||
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-setenv.Tpo $(DEPDIR)/go-setenv.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-setenv.c' object='go-setenv.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-setenv.lo `test -f 'runtime/go-setenv.c' || echo '$(srcdir)/'`runtime/go-setenv.c
|
||||
|
||||
go-signal.lo: runtime/go-signal.c
|
||||
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-signal.lo -MD -MP -MF $(DEPDIR)/go-signal.Tpo -c -o go-signal.lo `test -f 'runtime/go-signal.c' || echo '$(srcdir)/'`runtime/go-signal.c
|
||||
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-signal.Tpo $(DEPDIR)/go-signal.Plo
|
||||
@ -4114,11 +4187,12 @@ html/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: html/check
|
||||
|
||||
http/http.lo: $(go_http_files) bufio.gox bytes.gox container/vector.gox \
|
||||
crypto/rand.gox crypto/tls.gox encoding/base64.gox fmt.gox \
|
||||
io.gox io/ioutil.gox log.gox mime.gox mime/multipart.gox \
|
||||
net.gox net/textproto.gox os.gox path.gox path/filepath.gox \
|
||||
sort.gox strconv.gox strings.gox sync.gox time.gox utf8.gox
|
||||
http/http.lo: $(go_http_files) bufio.gox bytes.gox compress/gzip.gox \
|
||||
container/vector.gox crypto/rand.gox crypto/tls.gox \
|
||||
encoding/base64.gox fmt.gox io.gox io/ioutil.gox log.gox \
|
||||
mime.gox mime/multipart.gox net.gox net/textproto.gox os.gox \
|
||||
path.gox path/filepath.gox sort.gox strconv.gox strings.gox \
|
||||
sync.gox time.gox utf8.gox
|
||||
$(BUILDPACKAGE)
|
||||
http/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
@ -4158,7 +4232,7 @@ math/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: math/check
|
||||
|
||||
mime/mime.lo: $(go_mime_files) bufio.gox bytes.gox os.gox strings.gox \
|
||||
mime/mime.lo: $(go_mime_files) bufio.gox bytes.gox fmt.gox os.gox strings.gox \
|
||||
sync.gox unicode.gox
|
||||
$(BUILDPACKAGE)
|
||||
mime/check: $(CHECK_DEPS)
|
||||
@ -4166,8 +4240,8 @@ mime/check: $(CHECK_DEPS)
|
||||
.PHONY: mime/check
|
||||
|
||||
net/net.lo: $(go_net_files) bytes.gox fmt.gox io.gox os.gox rand.gox \
|
||||
reflect.gox strconv.gox strings.gox sync.gox syscall.gox \
|
||||
time.gox
|
||||
reflect.gox sort.gox strconv.gox strings.gox sync.gox \
|
||||
syscall.gox time.gox
|
||||
$(BUILDPACKAGE)
|
||||
net/check: $(CHECK_DEPS)
|
||||
@$(CHECK_ON_REQUEST)
|
||||
@ -4348,8 +4422,8 @@ xml/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: xml/check
|
||||
|
||||
archive/tar.lo: $(go_archive_tar_files) bytes.gox io.gox os.gox strconv.gox \
|
||||
strings.gox
|
||||
archive/tar.lo: $(go_archive_tar_files) bytes.gox io.gox io/ioutil.gox os.gox \
|
||||
strconv.gox strings.gox
|
||||
$(BUILDPACKAGE)
|
||||
archive/tar/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) archive/tar
|
||||
@ -4551,8 +4625,7 @@ crypto/ripemd160/check: $(CHECK_DEPS)
|
||||
.PHONY: crypto/ripemd160/check
|
||||
|
||||
crypto/rsa.lo: $(go_crypto_rsa_files) big.gox crypto.gox crypto/sha1.gox \
|
||||
crypto/subtle.gox encoding/hex.gox hash.gox io.gox os.gox \
|
||||
sync.gox
|
||||
crypto/subtle.gox encoding/hex.gox hash.gox io.gox os.gox
|
||||
$(BUILDPACKAGE)
|
||||
crypto/rsa/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) crypto/rsa
|
||||
@ -4587,13 +4660,13 @@ crypto/subtle/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: crypto/subtle/check
|
||||
|
||||
crypto/tls.lo: $(go_crypto_tls_files) big.gox bufio.gox bytes.gox \
|
||||
container/list.gox crypto.gox crypto/aes.gox crypto/cipher.gox \
|
||||
crypto/elliptic.gox crypto/hmac.gox crypto/md5.gox \
|
||||
crypto/rc4.gox crypto/rand.gox crypto/rsa.gox crypto/sha1.gox \
|
||||
crypto/subtle.gox crypto/rsa.gox crypto/sha1.gox \
|
||||
crypto/x509.gox encoding/pem.gox fmt.gox hash.gox io.gox \
|
||||
io/ioutil.gox net.gox os.gox strings.gox sync.gox time.gox
|
||||
crypto/tls.lo: $(go_crypto_tls_files) big.gox bytes.gox crypto.gox \
|
||||
crypto/aes.gox crypto/cipher.gox crypto/elliptic.gox \
|
||||
crypto/hmac.gox crypto/md5.gox crypto/rand.gox crypto/rc4.gox \
|
||||
crypto/rsa.gox crypto/sha1.gox crypto/subtle.gox \
|
||||
crypto/x509.gox encoding/pem.gox hash.gox io.gox \
|
||||
io/ioutil.gox net.gox os.gox strconv.gox strings.gox sync.gox \
|
||||
time.gox
|
||||
$(BUILDPACKAGE)
|
||||
crypto/tls/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) crypto/tls
|
||||
@ -4607,9 +4680,10 @@ crypto/twofish/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: crypto/twofish/check
|
||||
|
||||
crypto/x509.lo: $(go_crypto_x509_files) asn1.gox big.gox container/vector.gox \
|
||||
crypto.gox crypto/rsa.gox crypto/sha1.gox hash.gox os.gox \
|
||||
strings.gox time.gox
|
||||
crypto/x509.lo: $(go_crypto_x509_files) asn1.gox big.gox bytes.gox \
|
||||
container/vector.gox crypto.gox crypto/rsa.gox \
|
||||
crypto/sha1.gox encoding/pem.gox hash.gox os.gox strings.gox \
|
||||
time.gox
|
||||
$(BUILDPACKAGE)
|
||||
crypto/x509/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) crypto/x509
|
||||
@ -4623,9 +4697,8 @@ crypto/xtea/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: crypto/xtea/check
|
||||
|
||||
crypto/openpgp/armor.lo: $(go_crypto_openpgp_armor_files) bytes.gox \
|
||||
crypto/openpgp/error.gox encoding/base64.gox \
|
||||
encoding/line.gox io.gox os.gox
|
||||
crypto/openpgp/armor.lo: $(go_crypto_openpgp_armor_files) bufio.gox bytes.gox \
|
||||
crypto/openpgp/error.gox encoding/base64.gox io.gox os.gox
|
||||
$(BUILDPACKAGE)
|
||||
crypto/openpgp/armor/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) crypto/openpgp/armor
|
||||
@ -4777,7 +4850,7 @@ exp/datafmt/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: exp/datafmt/check
|
||||
|
||||
exp/draw.lo: $(go_exp_draw_files) image.gox os.gox
|
||||
exp/draw.lo: $(go_exp_draw_files) image.gox image/ycbcr.gox os.gox
|
||||
$(BUILDPACKAGE)
|
||||
exp/draw/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) exp/draw
|
||||
@ -4851,6 +4924,15 @@ go/typechecker/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: go/typechecker/check
|
||||
|
||||
go/types.lo: $(go_go_types_files) big.gox bufio.gox fmt.gox go/ast.gox \
|
||||
go/token.gox io.gox os.gox path/filepath.gox runtime.gox \
|
||||
scanner.gox strconv.gox strings.gox
|
||||
$(BUILDPACKAGE)
|
||||
go/types/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) go/types
|
||||
@$(CHECK)
|
||||
.PHONY: go/types/check
|
||||
|
||||
hash/adler32.lo: $(go_hash_adler32_files) hash.gox os.gox
|
||||
$(BUILDPACKAGE)
|
||||
hash/adler32/check: $(CHECK_DEPS)
|
||||
@ -4879,15 +4961,25 @@ hash/fnv/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: hash/fnv/check
|
||||
|
||||
http/cgi.lo: $(go_http_cgi_files) bufio.gox bytes.gox encoding/line.gox \
|
||||
exec.gox fmt.gox http.gox io.gox io/ioutil.gox log.gox \
|
||||
os.gox path/filepath.gox regexp.gox strconv.gox strings.gox
|
||||
http/cgi.lo: $(go_http_cgi_files) bufio.gox bytes.gox crypto/tls.gox \
|
||||
exec.gox fmt.gox http.gox net.gox io.gox io/ioutil.gox \
|
||||
log.gox os.gox path/filepath.gox regexp.gox strconv.gox \
|
||||
strings.gox
|
||||
$(BUILDPACKAGE)
|
||||
http/cgi/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) http/cgi
|
||||
@$(CHECK)
|
||||
.PHONY: http/cgi/check
|
||||
|
||||
http/fcgi.lo: $(go_http_fcgi_files) bufio.gox bytes.gox encoding/binary.gox \
|
||||
fmt.gox http.gox http/cgi.gox io.gox net.gox os.gox sync.gox \
|
||||
time.gox
|
||||
$(BUILDPACKAGE)
|
||||
http/fcgi/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) http/fcgi
|
||||
@$(CHECK)
|
||||
.PHONY: http/fcgi/check
|
||||
|
||||
http/httptest.lo: $(go_http_httptest_files) bytes.gox crypto/rand.gox \
|
||||
crypto/tls.gox fmt.gox http.gox net.gox os.gox time.gox
|
||||
$(BUILDPACKAGE)
|
||||
@ -4896,15 +4988,33 @@ http/httptest/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: http/httptest/check
|
||||
|
||||
http/pprof.lo: $(go_http_pprof_files) bufio.gox fmt.gox http.gox os.gox \
|
||||
runtime.gox runtime/pprof.gox strconv.gox strings.gox
|
||||
http/pprof.lo: $(go_http_pprof_files) bufio.gox bytes.gox fmt.gox http.gox \
|
||||
os.gox runtime.gox runtime/pprof.gox strconv.gox strings.gox
|
||||
$(BUILDPACKAGE)
|
||||
http/pprof/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) http/pprof
|
||||
@$(CHECK)
|
||||
.PHONY: http/pprof/check
|
||||
|
||||
image/jpeg.lo: $(go_image_jpeg_files) bufio.gox image.gox io.gox os.gox
|
||||
http/spdy.lo: $(go_http_spdy_files) bytes.gox compress/zlib.gox \
|
||||
encoding/binary.gox http.gox io.gox os.gox strconv.gox \
|
||||
strings.gox sync.gox
|
||||
$(BUILDPACKAGE)
|
||||
http/spdy/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) http/spdy
|
||||
@$(CHECK)
|
||||
.PHONY: http/spdy/check
|
||||
|
||||
image/gif.lo: $(go_image_gif_files) bufio.gox compress/lzw.gox fmt.gox \
|
||||
image.gox io.gox os.gox
|
||||
$(BUILDPACKAGE)
|
||||
image/gif/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) image/gif
|
||||
@$(CHECK)
|
||||
.PHONY: image/gif/check
|
||||
|
||||
image/jpeg.lo: $(go_image_jpeg_files) bufio.gox image.gox image/ycbcr.gox \
|
||||
io.gox os.gox
|
||||
$(BUILDPACKAGE)
|
||||
image/jpeg/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) image/jpeg
|
||||
@ -4919,6 +5029,21 @@ image/png/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: image/png/check
|
||||
|
||||
image/tiff.lo: $(go_image_tiff_files) compress/lzw.gox compress/zlib.gox \
|
||||
encoding/binary.gox image.gox io.gox io/ioutil.gox os.gox
|
||||
$(BUILDPACKAGE)
|
||||
image/tiff/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) image/tiff
|
||||
@$(CHECK)
|
||||
.PHONY: image/tiff/check
|
||||
|
||||
image/ycbcr.lo: $(go_image_ycbcr_files) image.gox
|
||||
$(BUILDPACKAGE)
|
||||
image/ycbcr/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) image/ycbcr
|
||||
@$(CHECK)
|
||||
.PHONY: image/ycbcr/check
|
||||
|
||||
index/suffixarray.lo: $(go_index_suffixarray_files) bytes.gox regexp.gox \
|
||||
sort.gox
|
||||
$(BUILDPACKAGE)
|
||||
@ -4935,8 +5060,9 @@ io/ioutil/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: io/ioutil/check
|
||||
|
||||
mime/multipart.lo: $(go_mime_multipart_files) bufio.gox bytes.gox io.gox \
|
||||
mime.gox net/textproto.gox os.gox regexp.gox strings.gox
|
||||
mime/multipart.lo: $(go_mime_multipart_files) bufio.gox bytes.gox fmt.gox \
|
||||
io.gox io/ioutil.gox mime.gox net/textproto.gox os.gox \
|
||||
regexp.gox
|
||||
$(BUILDPACKAGE)
|
||||
mime/multipart/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) mime/multipart
|
||||
@ -4963,6 +5089,14 @@ os/inotify/check: $(CHECK_DEPS)
|
||||
@$(CHECK)
|
||||
.PHONY: os/inotify/check
|
||||
|
||||
os/user.lo: $(go_os_user_files) fmt.gox os.gox runtime.gox strconv.gox \
|
||||
strings.gox syscall.gox
|
||||
$(BUILDPACKAGE)
|
||||
os/user/check: $(CHECK_DEPS)
|
||||
@$(MKDIR_P) os/user
|
||||
@$(CHECK)
|
||||
.PHONY: os/user/check
|
||||
|
||||
os/signal.lo: $(go_os_signal_files) runtime.gox strconv.gox
|
||||
$(BUILDPACKAGE)
|
||||
os/signal/check: $(CHECK_DEPS)
|
||||
@ -5284,6 +5418,8 @@ go/token.gox: go/token.lo
|
||||
$(BUILDGOX)
|
||||
go/typechecker.gox: go/typechecker.lo
|
||||
$(BUILDGOX)
|
||||
go/types.gox: go/types.lo
|
||||
$(BUILDGOX)
|
||||
|
||||
hash/adler32.gox: hash/adler32.lo
|
||||
$(BUILDGOX)
|
||||
@ -5296,15 +5432,25 @@ hash/fnv.gox: hash/fnv.lo
|
||||
|
||||
http/cgi.gox: http/cgi.lo
|
||||
$(BUILDGOX)
|
||||
http/fcgi.gox: http/fcgi.lo
|
||||
$(BUILDGOX)
|
||||
http/httptest.gox: http/httptest.lo
|
||||
$(BUILDGOX)
|
||||
http/pprof.gox: http/pprof.lo
|
||||
$(BUILDGOX)
|
||||
http/spdy.gox: http/spdy.lo
|
||||
$(BUILDGOX)
|
||||
|
||||
image/gif.gox: image/gif.lo
|
||||
$(BUILDGOX)
|
||||
image/jpeg.gox: image/jpeg.lo
|
||||
$(BUILDGOX)
|
||||
image/png.gox: image/png.lo
|
||||
$(BUILDGOX)
|
||||
image/tiff.gox: image/tiff.lo
|
||||
$(BUILDGOX)
|
||||
image/ycbcr.gox: image/ycbcr.lo
|
||||
$(BUILDGOX)
|
||||
|
||||
index/suffixarray.gox: index/suffixarray.lo
|
||||
$(BUILDGOX)
|
||||
@ -5322,6 +5468,8 @@ net/textproto.gox: net/textproto.lo
|
||||
|
||||
os/inotify.gox: os/inotify.lo
|
||||
$(BUILDGOX)
|
||||
os/user.gox: os/user.lo
|
||||
$(BUILDGOX)
|
||||
os/signal.gox: os/signal.lo
|
||||
$(BUILDGOX)
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// The tar package implements access to tar archives.
|
||||
// Package tar implements access to tar archives.
|
||||
// It aims to cover most of the variations, including those produced
|
||||
// by GNU and BSD tars.
|
||||
//
|
||||
|
@ -10,6 +10,7 @@ package tar
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
@ -27,13 +28,13 @@ var (
|
||||
// tr := tar.NewReader(r)
|
||||
// for {
|
||||
// hdr, err := tr.Next()
|
||||
// if err != nil {
|
||||
// // handle error
|
||||
// }
|
||||
// if hdr == nil {
|
||||
// if err == os.EOF {
|
||||
// // end of tar archive
|
||||
// break
|
||||
// }
|
||||
// if err != nil {
|
||||
// // handle error
|
||||
// }
|
||||
// io.Copy(data, tr)
|
||||
// }
|
||||
type Reader struct {
|
||||
@ -84,12 +85,6 @@ func (tr *Reader) octal(b []byte) int64 {
|
||||
return int64(x)
|
||||
}
|
||||
|
||||
type ignoreWriter struct{}
|
||||
|
||||
func (ignoreWriter) Write(b []byte) (n int, err os.Error) {
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
// Skip any unread bytes in the existing file entry, as well as any alignment padding.
|
||||
func (tr *Reader) skipUnread() {
|
||||
nr := tr.nb + tr.pad // number of bytes to skip
|
||||
@ -99,7 +94,7 @@ func (tr *Reader) skipUnread() {
|
||||
return
|
||||
}
|
||||
}
|
||||
_, tr.err = io.Copyn(ignoreWriter{}, tr.r, nr)
|
||||
_, tr.err = io.Copyn(ioutil.Discard, tr.r, nr)
|
||||
}
|
||||
|
||||
func (tr *Reader) verifyChecksum(header []byte) bool {
|
||||
|
@ -3,7 +3,7 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
The zip package provides support for reading ZIP archives.
|
||||
Package zip provides support for reading ZIP archives.
|
||||
|
||||
See: http://www.pkware.com/documents/casestudies/APPNOTE.TXT
|
||||
|
||||
@ -35,6 +35,11 @@ type Reader struct {
|
||||
Comment string
|
||||
}
|
||||
|
||||
type ReadCloser struct {
|
||||
f *os.File
|
||||
Reader
|
||||
}
|
||||
|
||||
type File struct {
|
||||
FileHeader
|
||||
zipr io.ReaderAt
|
||||
@ -47,43 +52,60 @@ func (f *File) hasDataDescriptor() bool {
|
||||
return f.Flags&0x8 != 0
|
||||
}
|
||||
|
||||
// OpenReader will open the Zip file specified by name and return a Reader.
|
||||
func OpenReader(name string) (*Reader, os.Error) {
|
||||
// OpenReader will open the Zip file specified by name and return a ReaderCloser.
|
||||
func OpenReader(name string) (*ReadCloser, os.Error) {
|
||||
f, err := os.Open(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fi, err := f.Stat()
|
||||
if err != nil {
|
||||
f.Close()
|
||||
return nil, err
|
||||
}
|
||||
return NewReader(f, fi.Size)
|
||||
r := new(ReadCloser)
|
||||
if err := r.init(f, fi.Size); err != nil {
|
||||
f.Close()
|
||||
return nil, err
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// NewReader returns a new Reader reading from r, which is assumed to
|
||||
// have the given size in bytes.
|
||||
func NewReader(r io.ReaderAt, size int64) (*Reader, os.Error) {
|
||||
zr := new(Reader)
|
||||
if err := zr.init(r, size); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return zr, nil
|
||||
}
|
||||
|
||||
func (z *Reader) init(r io.ReaderAt, size int64) os.Error {
|
||||
end, err := readDirectoryEnd(r, size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
z := &Reader{
|
||||
r: r,
|
||||
File: make([]*File, end.directoryRecords),
|
||||
Comment: end.comment,
|
||||
return err
|
||||
}
|
||||
z.r = r
|
||||
z.File = make([]*File, end.directoryRecords)
|
||||
z.Comment = end.comment
|
||||
rs := io.NewSectionReader(r, 0, size)
|
||||
if _, err = rs.Seek(int64(end.directoryOffset), os.SEEK_SET); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
buf := bufio.NewReader(rs)
|
||||
for i := range z.File {
|
||||
z.File[i] = &File{zipr: r, zipsize: size}
|
||||
if err := readDirectoryHeader(z.File[i], buf); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
return z, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// Close closes the Zip file, rendering it unusable for I/O.
|
||||
func (rc *ReadCloser) Close() os.Error {
|
||||
return rc.f.Close()
|
||||
}
|
||||
|
||||
// Open returns a ReadCloser that provides access to the File's contents.
|
||||
|
@ -76,6 +76,12 @@ func readTestZip(t *testing.T, zt ZipTest) {
|
||||
return
|
||||
}
|
||||
|
||||
// bail if file is not zip
|
||||
if err == FormatError {
|
||||
return
|
||||
}
|
||||
defer z.Close()
|
||||
|
||||
// bail here if no Files expected to be tested
|
||||
// (there may actually be files in the zip, but we don't care)
|
||||
if zt.File == nil {
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// The asn1 package implements parsing of DER-encoded ASN.1 data structures,
|
||||
// Package asn1 implements parsing of DER-encoded ASN.1 data structures,
|
||||
// as defined in ITU-T Rec X.690.
|
||||
//
|
||||
// See also ``A Layman's Guide to a Subset of ASN.1, BER, and DER,''
|
||||
@ -373,7 +373,7 @@ func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset i
|
||||
// parseSequenceOf is used for SEQUENCE OF and SET OF values. It tries to parse
|
||||
// a number of ASN.1 values from the given byte array and returns them as a
|
||||
// slice of Go values of the given type.
|
||||
func parseSequenceOf(bytes []byte, sliceType *reflect.SliceType, elemType reflect.Type) (ret *reflect.SliceValue, err os.Error) {
|
||||
func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type) (ret reflect.Value, err os.Error) {
|
||||
expectedTag, compoundType, ok := getUniversalType(elemType)
|
||||
if !ok {
|
||||
err = StructuralError{"unknown Go type for slice"}
|
||||
@ -409,7 +409,7 @@ func parseSequenceOf(bytes []byte, sliceType *reflect.SliceType, elemType reflec
|
||||
params := fieldParameters{}
|
||||
offset := 0
|
||||
for i := 0; i < numElements; i++ {
|
||||
offset, err = parseField(ret.Elem(i), bytes, offset, params)
|
||||
offset, err = parseField(ret.Index(i), bytes, offset, params)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -418,13 +418,13 @@ func parseSequenceOf(bytes []byte, sliceType *reflect.SliceType, elemType reflec
|
||||
}
|
||||
|
||||
var (
|
||||
bitStringType = reflect.Typeof(BitString{})
|
||||
objectIdentifierType = reflect.Typeof(ObjectIdentifier{})
|
||||
enumeratedType = reflect.Typeof(Enumerated(0))
|
||||
flagType = reflect.Typeof(Flag(false))
|
||||
timeType = reflect.Typeof(&time.Time{})
|
||||
rawValueType = reflect.Typeof(RawValue{})
|
||||
rawContentsType = reflect.Typeof(RawContent(nil))
|
||||
bitStringType = reflect.TypeOf(BitString{})
|
||||
objectIdentifierType = reflect.TypeOf(ObjectIdentifier{})
|
||||
enumeratedType = reflect.TypeOf(Enumerated(0))
|
||||
flagType = reflect.TypeOf(Flag(false))
|
||||
timeType = reflect.TypeOf(&time.Time{})
|
||||
rawValueType = reflect.TypeOf(RawValue{})
|
||||
rawContentsType = reflect.TypeOf(RawContent(nil))
|
||||
)
|
||||
|
||||
// invalidLength returns true iff offset + length > sliceLength, or if the
|
||||
@ -461,13 +461,12 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
|
||||
}
|
||||
result := RawValue{t.class, t.tag, t.isCompound, bytes[offset : offset+t.length], bytes[initOffset : offset+t.length]}
|
||||
offset += t.length
|
||||
v.(*reflect.StructValue).Set(reflect.NewValue(result).(*reflect.StructValue))
|
||||
v.Set(reflect.ValueOf(result))
|
||||
return
|
||||
}
|
||||
|
||||
// Deal with the ANY type.
|
||||
if ifaceType, ok := fieldType.(*reflect.InterfaceType); ok && ifaceType.NumMethod() == 0 {
|
||||
ifaceValue := v.(*reflect.InterfaceValue)
|
||||
if ifaceType := fieldType; ifaceType.Kind() == reflect.Interface && ifaceType.NumMethod() == 0 {
|
||||
var t tagAndLength
|
||||
t, offset, err = parseTagAndLength(bytes, offset)
|
||||
if err != nil {
|
||||
@ -506,7 +505,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
|
||||
return
|
||||
}
|
||||
if result != nil {
|
||||
ifaceValue.Set(reflect.NewValue(result))
|
||||
v.Set(reflect.ValueOf(result))
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -536,9 +535,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
|
||||
err = StructuralError{"Zero length explicit tag was not an asn1.Flag"}
|
||||
return
|
||||
}
|
||||
|
||||
flagValue := v.(*reflect.BoolValue)
|
||||
flagValue.Set(true)
|
||||
v.SetBool(true)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
@ -606,23 +603,20 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
|
||||
switch fieldType {
|
||||
case objectIdentifierType:
|
||||
newSlice, err1 := parseObjectIdentifier(innerBytes)
|
||||
sliceValue := v.(*reflect.SliceValue)
|
||||
sliceValue.Set(reflect.MakeSlice(sliceValue.Type().(*reflect.SliceType), len(newSlice), len(newSlice)))
|
||||
v.Set(reflect.MakeSlice(v.Type(), len(newSlice), len(newSlice)))
|
||||
if err1 == nil {
|
||||
reflect.Copy(sliceValue, reflect.NewValue(newSlice).(reflect.ArrayOrSliceValue))
|
||||
reflect.Copy(v, reflect.ValueOf(newSlice))
|
||||
}
|
||||
err = err1
|
||||
return
|
||||
case bitStringType:
|
||||
structValue := v.(*reflect.StructValue)
|
||||
bs, err1 := parseBitString(innerBytes)
|
||||
if err1 == nil {
|
||||
structValue.Set(reflect.NewValue(bs).(*reflect.StructValue))
|
||||
v.Set(reflect.ValueOf(bs))
|
||||
}
|
||||
err = err1
|
||||
return
|
||||
case timeType:
|
||||
ptrValue := v.(*reflect.PtrValue)
|
||||
var time *time.Time
|
||||
var err1 os.Error
|
||||
if universalTag == tagUTCTime {
|
||||
@ -631,55 +625,53 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
|
||||
time, err1 = parseGeneralizedTime(innerBytes)
|
||||
}
|
||||
if err1 == nil {
|
||||
ptrValue.Set(reflect.NewValue(time).(*reflect.PtrValue))
|
||||
v.Set(reflect.ValueOf(time))
|
||||
}
|
||||
err = err1
|
||||
return
|
||||
case enumeratedType:
|
||||
parsedInt, err1 := parseInt(innerBytes)
|
||||
enumValue := v.(*reflect.IntValue)
|
||||
if err1 == nil {
|
||||
enumValue.Set(int64(parsedInt))
|
||||
v.SetInt(int64(parsedInt))
|
||||
}
|
||||
err = err1
|
||||
return
|
||||
case flagType:
|
||||
flagValue := v.(*reflect.BoolValue)
|
||||
flagValue.Set(true)
|
||||
v.SetBool(true)
|
||||
return
|
||||
}
|
||||
switch val := v.(type) {
|
||||
case *reflect.BoolValue:
|
||||
switch val := v; val.Kind() {
|
||||
case reflect.Bool:
|
||||
parsedBool, err1 := parseBool(innerBytes)
|
||||
if err1 == nil {
|
||||
val.Set(parsedBool)
|
||||
val.SetBool(parsedBool)
|
||||
}
|
||||
err = err1
|
||||
return
|
||||
case *reflect.IntValue:
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
switch val.Type().Kind() {
|
||||
case reflect.Int:
|
||||
parsedInt, err1 := parseInt(innerBytes)
|
||||
if err1 == nil {
|
||||
val.Set(int64(parsedInt))
|
||||
val.SetInt(int64(parsedInt))
|
||||
}
|
||||
err = err1
|
||||
return
|
||||
case reflect.Int64:
|
||||
parsedInt, err1 := parseInt64(innerBytes)
|
||||
if err1 == nil {
|
||||
val.Set(parsedInt)
|
||||
val.SetInt(parsedInt)
|
||||
}
|
||||
err = err1
|
||||
return
|
||||
}
|
||||
case *reflect.StructValue:
|
||||
structType := fieldType.(*reflect.StructType)
|
||||
case reflect.Struct:
|
||||
structType := fieldType
|
||||
|
||||
if structType.NumField() > 0 &&
|
||||
structType.Field(0).Type == rawContentsType {
|
||||
bytes := bytes[initOffset:offset]
|
||||
val.Field(0).SetValue(reflect.NewValue(RawContent(bytes)))
|
||||
val.Field(0).Set(reflect.ValueOf(RawContent(bytes)))
|
||||
}
|
||||
|
||||
innerOffset := 0
|
||||
@ -697,11 +689,11 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
|
||||
// adding elements to the end has been used in X.509 as the
|
||||
// version numbers have increased.
|
||||
return
|
||||
case *reflect.SliceValue:
|
||||
sliceType := fieldType.(*reflect.SliceType)
|
||||
case reflect.Slice:
|
||||
sliceType := fieldType
|
||||
if sliceType.Elem().Kind() == reflect.Uint8 {
|
||||
val.Set(reflect.MakeSlice(sliceType, len(innerBytes), len(innerBytes)))
|
||||
reflect.Copy(val, reflect.NewValue(innerBytes).(reflect.ArrayOrSliceValue))
|
||||
reflect.Copy(val, reflect.ValueOf(innerBytes))
|
||||
return
|
||||
}
|
||||
newSlice, err1 := parseSequenceOf(innerBytes, sliceType, sliceType.Elem())
|
||||
@ -710,7 +702,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
|
||||
}
|
||||
err = err1
|
||||
return
|
||||
case *reflect.StringValue:
|
||||
case reflect.String:
|
||||
var v string
|
||||
switch universalTag {
|
||||
case tagPrintableString:
|
||||
@ -729,7 +721,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
|
||||
err = SyntaxError{fmt.Sprintf("internal error: unknown string type %d", universalTag)}
|
||||
}
|
||||
if err == nil {
|
||||
val.Set(v)
|
||||
val.SetString(v)
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -748,9 +740,9 @@ func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) {
|
||||
if params.defaultValue == nil {
|
||||
return
|
||||
}
|
||||
switch val := v.(type) {
|
||||
case *reflect.IntValue:
|
||||
val.Set(*params.defaultValue)
|
||||
switch val := v; val.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
val.SetInt(*params.defaultValue)
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -806,7 +798,7 @@ func Unmarshal(b []byte, val interface{}) (rest []byte, err os.Error) {
|
||||
// UnmarshalWithParams allows field parameters to be specified for the
|
||||
// top-level element. The form of the params is the same as the field tags.
|
||||
func UnmarshalWithParams(b []byte, val interface{}, params string) (rest []byte, err os.Error) {
|
||||
v := reflect.NewValue(val).(*reflect.PtrValue).Elem()
|
||||
v := reflect.ValueOf(val).Elem()
|
||||
offset, err := parseField(v, b, 0, parseFieldParameters(params))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -267,11 +267,6 @@ func TestParseFieldParameters(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
type unmarshalTest struct {
|
||||
in []byte
|
||||
out interface{}
|
||||
}
|
||||
|
||||
type TestObjectIdentifierStruct struct {
|
||||
OID ObjectIdentifier
|
||||
}
|
||||
@ -290,7 +285,10 @@ type TestElementsAfterString struct {
|
||||
A, B int
|
||||
}
|
||||
|
||||
var unmarshalTestData []unmarshalTest = []unmarshalTest{
|
||||
var unmarshalTestData = []struct {
|
||||
in []byte
|
||||
out interface{}
|
||||
}{
|
||||
{[]byte{0x02, 0x01, 0x42}, newInt(0x42)},
|
||||
{[]byte{0x30, 0x08, 0x06, 0x06, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d}, &TestObjectIdentifierStruct{[]int{1, 2, 840, 113549}}},
|
||||
{[]byte{0x03, 0x04, 0x06, 0x6e, 0x5d, 0xc0}, &BitString{[]byte{110, 93, 192}, 18}},
|
||||
@ -309,9 +307,7 @@ var unmarshalTestData []unmarshalTest = []unmarshalTest{
|
||||
|
||||
func TestUnmarshal(t *testing.T) {
|
||||
for i, test := range unmarshalTestData {
|
||||
pv := reflect.MakeZero(reflect.NewValue(test.out).Type())
|
||||
zv := reflect.MakeZero(pv.Type().(*reflect.PtrType).Elem())
|
||||
pv.(*reflect.PtrValue).PointTo(zv)
|
||||
pv := reflect.New(reflect.TypeOf(test.out).Elem())
|
||||
val := pv.Interface()
|
||||
_, err := Unmarshal(test.in, val)
|
||||
if err != nil {
|
||||
|
@ -133,14 +133,14 @@ func getUniversalType(t reflect.Type) (tagNumber int, isCompound, ok bool) {
|
||||
case enumeratedType:
|
||||
return tagEnum, false, true
|
||||
}
|
||||
switch t := t.(type) {
|
||||
case *reflect.BoolType:
|
||||
switch t.Kind() {
|
||||
case reflect.Bool:
|
||||
return tagBoolean, false, true
|
||||
case *reflect.IntType:
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return tagInteger, false, true
|
||||
case *reflect.StructType:
|
||||
case reflect.Struct:
|
||||
return tagSequence, true, true
|
||||
case *reflect.SliceType:
|
||||
case reflect.Slice:
|
||||
if t.Elem().Kind() == reflect.Uint8 {
|
||||
return tagOctetString, false, true
|
||||
}
|
||||
@ -148,7 +148,7 @@ func getUniversalType(t reflect.Type) (tagNumber int, isCompound, ok bool) {
|
||||
return tagSet, true, true
|
||||
}
|
||||
return tagSequence, true, true
|
||||
case *reflect.StringType:
|
||||
case reflect.String:
|
||||
return tagPrintableString, false, true
|
||||
}
|
||||
return 0, false, false
|
||||
|
@ -125,6 +125,28 @@ func int64Length(i int64) (numBytes int) {
|
||||
return
|
||||
}
|
||||
|
||||
func marshalLength(out *forkableWriter, i int) (err os.Error) {
|
||||
n := lengthLength(i)
|
||||
|
||||
for ; n > 0; n-- {
|
||||
err = out.WriteByte(byte(i >> uint((n-1)*8)))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func lengthLength(i int) (numBytes int) {
|
||||
numBytes = 1
|
||||
for i > 255 {
|
||||
numBytes++
|
||||
i >>= 8
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func marshalTagAndLength(out *forkableWriter, t tagAndLength) (err os.Error) {
|
||||
b := uint8(t.class) << 6
|
||||
if t.isCompound {
|
||||
@ -149,12 +171,12 @@ func marshalTagAndLength(out *forkableWriter, t tagAndLength) (err os.Error) {
|
||||
}
|
||||
|
||||
if t.length >= 128 {
|
||||
l := int64Length(int64(t.length))
|
||||
l := lengthLength(t.length)
|
||||
err = out.WriteByte(0x80 | byte(l))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = marshalInt64(out, int64(t.length))
|
||||
err = marshalLength(out, t.length)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -314,28 +336,28 @@ func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameter
|
||||
return marshalObjectIdentifier(out, value.Interface().(ObjectIdentifier))
|
||||
}
|
||||
|
||||
switch v := value.(type) {
|
||||
case *reflect.BoolValue:
|
||||
if v.Get() {
|
||||
switch v := value; v.Kind() {
|
||||
case reflect.Bool:
|
||||
if v.Bool() {
|
||||
return out.WriteByte(255)
|
||||
} else {
|
||||
return out.WriteByte(0)
|
||||
}
|
||||
case *reflect.IntValue:
|
||||
return marshalInt64(out, int64(v.Get()))
|
||||
case *reflect.StructValue:
|
||||
t := v.Type().(*reflect.StructType)
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return marshalInt64(out, int64(v.Int()))
|
||||
case reflect.Struct:
|
||||
t := v.Type()
|
||||
|
||||
startingField := 0
|
||||
|
||||
// If the first element of the structure is a non-empty
|
||||
// RawContents, then we don't bother serialising the rest.
|
||||
if t.NumField() > 0 && t.Field(0).Type == rawContentsType {
|
||||
s := v.Field(0).(*reflect.SliceValue)
|
||||
s := v.Field(0)
|
||||
if s.Len() > 0 {
|
||||
bytes := make([]byte, s.Len())
|
||||
for i := 0; i < s.Len(); i++ {
|
||||
bytes[i] = uint8(s.Elem(i).(*reflect.UintValue).Get())
|
||||
bytes[i] = uint8(s.Index(i).Uint())
|
||||
}
|
||||
/* The RawContents will contain the tag and
|
||||
* length fields but we'll also be writing
|
||||
@ -357,12 +379,12 @@ func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameter
|
||||
}
|
||||
}
|
||||
return
|
||||
case *reflect.SliceValue:
|
||||
sliceType := v.Type().(*reflect.SliceType)
|
||||
case reflect.Slice:
|
||||
sliceType := v.Type()
|
||||
if sliceType.Elem().Kind() == reflect.Uint8 {
|
||||
bytes := make([]byte, v.Len())
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
bytes[i] = uint8(v.Elem(i).(*reflect.UintValue).Get())
|
||||
bytes[i] = uint8(v.Index(i).Uint())
|
||||
}
|
||||
_, err = out.Write(bytes)
|
||||
return
|
||||
@ -372,17 +394,17 @@ func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameter
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
var pre *forkableWriter
|
||||
pre, out = out.fork()
|
||||
err = marshalField(pre, v.Elem(i), params)
|
||||
err = marshalField(pre, v.Index(i), params)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
case *reflect.StringValue:
|
||||
case reflect.String:
|
||||
if params.stringType == tagIA5String {
|
||||
return marshalIA5String(out, v.Get())
|
||||
return marshalIA5String(out, v.String())
|
||||
} else {
|
||||
return marshalPrintableString(out, v.Get())
|
||||
return marshalPrintableString(out, v.String())
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -392,7 +414,7 @@ func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameter
|
||||
|
||||
func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters) (err os.Error) {
|
||||
// If the field is an interface{} then recurse into it.
|
||||
if v, ok := v.(*reflect.InterfaceValue); ok && v.Type().(*reflect.InterfaceType).NumMethod() == 0 {
|
||||
if v.Kind() == reflect.Interface && v.Type().NumMethod() == 0 {
|
||||
return marshalField(out, v.Elem(), params)
|
||||
}
|
||||
|
||||
@ -406,7 +428,7 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
|
||||
return
|
||||
}
|
||||
|
||||
if params.optional && reflect.DeepEqual(v.Interface(), reflect.MakeZero(v.Type()).Interface()) {
|
||||
if params.optional && reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) {
|
||||
return
|
||||
}
|
||||
|
||||
@ -471,7 +493,7 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
|
||||
// Marshal returns the ASN.1 encoding of val.
|
||||
func Marshal(val interface{}) ([]byte, os.Error) {
|
||||
var out bytes.Buffer
|
||||
v := reflect.NewValue(val)
|
||||
v := reflect.ValueOf(val)
|
||||
f := newForkableWriter()
|
||||
err := marshalField(f, v, fieldParameters{})
|
||||
if err != nil {
|
||||
|
@ -77,6 +77,30 @@ var marshalTests = []marshalTest{
|
||||
{ObjectIdentifier([]int{1, 2, 3, 4}), "06032a0304"},
|
||||
{ObjectIdentifier([]int{1, 2, 840, 133549, 1, 1, 5}), "06092a864888932d010105"},
|
||||
{"test", "130474657374"},
|
||||
{
|
||||
"" +
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // This is 127 times 'x'
|
||||
"137f" +
|
||||
"7878787878787878787878787878787878787878787878787878787878787878" +
|
||||
"7878787878787878787878787878787878787878787878787878787878787878" +
|
||||
"7878787878787878787878787878787878787878787878787878787878787878" +
|
||||
"78787878787878787878787878787878787878787878787878787878787878",
|
||||
},
|
||||
{
|
||||
"" +
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // This is 128 times 'x'
|
||||
"138180" +
|
||||
"7878787878787878787878787878787878787878787878787878787878787878" +
|
||||
"7878787878787878787878787878787878787878787878787878787878787878" +
|
||||
"7878787878787878787878787878787878787878787878787878787878787878" +
|
||||
"7878787878787878787878787878787878787878787878787878787878787878",
|
||||
},
|
||||
{ia5StringTest{"test"}, "3006160474657374"},
|
||||
{printableStringTest{"test"}, "3006130474657374"},
|
||||
{printableStringTest{"test*"}, "30071305746573742a"},
|
||||
|
@ -337,6 +337,10 @@ func fmtbase(ch int) int {
|
||||
// 'x' (hexadecimal).
|
||||
//
|
||||
func (x *Int) Format(s fmt.State, ch int) {
|
||||
if x == nil {
|
||||
fmt.Fprint(s, "<nil>")
|
||||
return
|
||||
}
|
||||
if x.neg {
|
||||
fmt.Fprint(s, "-")
|
||||
}
|
||||
|
@ -2,11 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file contains operations on unsigned multi-precision integers.
|
||||
// These are the building blocks for the operations on signed integers
|
||||
// and rationals.
|
||||
|
||||
// This package implements multi-precision arithmetic (big numbers).
|
||||
// Package big implements multi-precision arithmetic (big numbers).
|
||||
// The following numeric types are supported:
|
||||
//
|
||||
// - Int signed integers
|
||||
@ -18,6 +14,10 @@
|
||||
//
|
||||
package big
|
||||
|
||||
// This file contains operations on unsigned multi-precision integers.
|
||||
// These are the building blocks for the operations on signed integers
|
||||
// and rationals.
|
||||
|
||||
import "rand"
|
||||
|
||||
// An unsigned integer x of the form
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This package implements buffered I/O. It wraps an io.Reader or io.Writer
|
||||
// Package bufio implements buffered I/O. It wraps an io.Reader or io.Writer
|
||||
// object, creating another object (Reader or Writer) that also implements
|
||||
// the interface but provides buffering and some help for textual I/O.
|
||||
package bufio
|
||||
@ -282,6 +282,33 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err os.Error) {
|
||||
panic("not reached")
|
||||
}
|
||||
|
||||
// ReadLine tries to return a single line, not including the end-of-line bytes.
|
||||
// If the line was too long for the buffer then isPrefix is set and the
|
||||
// beginning of the line is returned. The rest of the line will be returned
|
||||
// from future calls. isPrefix will be false when returning the last fragment
|
||||
// of the line. The returned buffer is only valid until the next call to
|
||||
// ReadLine. ReadLine either returns a non-nil line or it returns an error,
|
||||
// never both.
|
||||
func (b *Reader) ReadLine() (line []byte, isPrefix bool, err os.Error) {
|
||||
line, err = b.ReadSlice('\n')
|
||||
if err == ErrBufferFull {
|
||||
return line, true, nil
|
||||
}
|
||||
|
||||
if len(line) == 0 {
|
||||
return
|
||||
}
|
||||
err = nil
|
||||
|
||||
if line[len(line)-1] == '\n' {
|
||||
line = line[:len(line)-1]
|
||||
}
|
||||
if len(line) > 0 && line[len(line)-1] == '\r' {
|
||||
line = line[:len(line)-1]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ReadBytes reads until the first occurrence of delim in the input,
|
||||
// returning a slice containing the data up to and including the delimiter.
|
||||
// If ReadBytes encounters an error before finding a delimiter,
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
@ -570,3 +571,128 @@ func TestPeekThenUnreadRune(t *testing.T) {
|
||||
r.UnreadRune()
|
||||
r.ReadRune() // Used to panic here
|
||||
}
|
||||
|
||||
var testOutput = []byte("0123456789abcdefghijklmnopqrstuvwxy")
|
||||
var testInput = []byte("012\n345\n678\n9ab\ncde\nfgh\nijk\nlmn\nopq\nrst\nuvw\nxy")
|
||||
var testInputrn = []byte("012\r\n345\r\n678\r\n9ab\r\ncde\r\nfgh\r\nijk\r\nlmn\r\nopq\r\nrst\r\nuvw\r\nxy\r\n\n\r\n")
|
||||
|
||||
// TestReader wraps a []byte and returns reads of a specific length.
|
||||
type testReader struct {
|
||||
data []byte
|
||||
stride int
|
||||
}
|
||||
|
||||
func (t *testReader) Read(buf []byte) (n int, err os.Error) {
|
||||
n = t.stride
|
||||
if n > len(t.data) {
|
||||
n = len(t.data)
|
||||
}
|
||||
if n > len(buf) {
|
||||
n = len(buf)
|
||||
}
|
||||
copy(buf, t.data)
|
||||
t.data = t.data[n:]
|
||||
if len(t.data) == 0 {
|
||||
err = os.EOF
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func testReadLine(t *testing.T, input []byte) {
|
||||
//for stride := 1; stride < len(input); stride++ {
|
||||
for stride := 1; stride < 2; stride++ {
|
||||
done := 0
|
||||
reader := testReader{input, stride}
|
||||
l, _ := NewReaderSize(&reader, len(input)+1)
|
||||
for {
|
||||
line, isPrefix, err := l.ReadLine()
|
||||
if len(line) > 0 && err != nil {
|
||||
t.Errorf("ReadLine returned both data and error: %s", err)
|
||||
}
|
||||
if isPrefix {
|
||||
t.Errorf("ReadLine returned prefix")
|
||||
}
|
||||
if err != nil {
|
||||
if err != os.EOF {
|
||||
t.Fatalf("Got unknown error: %s", err)
|
||||
}
|
||||
break
|
||||
}
|
||||
if want := testOutput[done : done+len(line)]; !bytes.Equal(want, line) {
|
||||
t.Errorf("Bad line at stride %d: want: %x got: %x", stride, want, line)
|
||||
}
|
||||
done += len(line)
|
||||
}
|
||||
if done != len(testOutput) {
|
||||
t.Errorf("ReadLine didn't return everything: got: %d, want: %d (stride: %d)", done, len(testOutput), stride)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadLine(t *testing.T) {
|
||||
testReadLine(t, testInput)
|
||||
testReadLine(t, testInputrn)
|
||||
}
|
||||
|
||||
func TestLineTooLong(t *testing.T) {
|
||||
buf := bytes.NewBuffer([]byte("aaabbbcc\n"))
|
||||
l, _ := NewReaderSize(buf, 3)
|
||||
line, isPrefix, err := l.ReadLine()
|
||||
if !isPrefix || !bytes.Equal(line, []byte("aaa")) || err != nil {
|
||||
t.Errorf("bad result for first line: %x %s", line, err)
|
||||
}
|
||||
line, isPrefix, err = l.ReadLine()
|
||||
if !isPrefix || !bytes.Equal(line, []byte("bbb")) || err != nil {
|
||||
t.Errorf("bad result for second line: %x", line)
|
||||
}
|
||||
line, isPrefix, err = l.ReadLine()
|
||||
if isPrefix || !bytes.Equal(line, []byte("cc")) || err != nil {
|
||||
t.Errorf("bad result for third line: %x", line)
|
||||
}
|
||||
line, isPrefix, err = l.ReadLine()
|
||||
if isPrefix || err == nil {
|
||||
t.Errorf("expected no more lines: %x %s", line, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadAfterLines(t *testing.T) {
|
||||
line1 := "line1"
|
||||
restData := "line2\nline 3\n"
|
||||
inbuf := bytes.NewBuffer([]byte(line1 + "\n" + restData))
|
||||
outbuf := new(bytes.Buffer)
|
||||
maxLineLength := len(line1) + len(restData)/2
|
||||
l, _ := NewReaderSize(inbuf, maxLineLength)
|
||||
line, isPrefix, err := l.ReadLine()
|
||||
if isPrefix || err != nil || string(line) != line1 {
|
||||
t.Errorf("bad result for first line: isPrefix=%v err=%v line=%q", isPrefix, err, string(line))
|
||||
}
|
||||
n, err := io.Copy(outbuf, l)
|
||||
if int(n) != len(restData) || err != nil {
|
||||
t.Errorf("bad result for Read: n=%d err=%v", n, err)
|
||||
}
|
||||
if outbuf.String() != restData {
|
||||
t.Errorf("bad result for Read: got %q; expected %q", outbuf.String(), restData)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadEmptyBuffer(t *testing.T) {
|
||||
l, _ := NewReaderSize(bytes.NewBuffer(nil), 10)
|
||||
line, isPrefix, err := l.ReadLine()
|
||||
if err != os.EOF {
|
||||
t.Errorf("expected EOF from ReadLine, got '%s' %t %s", line, isPrefix, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLinesAfterRead(t *testing.T) {
|
||||
l, _ := NewReaderSize(bytes.NewBuffer([]byte("foo")), 10)
|
||||
_, err := ioutil.ReadAll(l)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
line, isPrefix, err := l.ReadLine()
|
||||
if err != os.EOF {
|
||||
t.Errorf("expected EOF from ReadLine, got '%s' %t %s", line, isPrefix, err)
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// The bytes package implements functions for the manipulation of byte slices.
|
||||
// Analogous to the facilities of the strings package.
|
||||
// Package bytes implements functions for the manipulation of byte slices.
|
||||
// It is analogous to the facilities of the strings package.
|
||||
package bytes
|
||||
|
||||
import (
|
||||
|
@ -2,8 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// The cmath package provides basic constants
|
||||
// and mathematical functions for complex numbers.
|
||||
// Package cmath provides basic constants and mathematical functions for
|
||||
// complex numbers.
|
||||
package cmath
|
||||
|
||||
import "math"
|
||||
|
@ -143,10 +143,18 @@ func (d *compressor) fillWindow(index int) (int, os.Error) {
|
||||
d.blockStart = math.MaxInt32
|
||||
}
|
||||
for i, h := range d.hashHead {
|
||||
d.hashHead[i] = max(h-wSize, -1)
|
||||
v := h - wSize
|
||||
if v < -1 {
|
||||
v = -1
|
||||
}
|
||||
d.hashHead[i] = v
|
||||
}
|
||||
for i, h := range d.hashPrev {
|
||||
d.hashPrev[i] = max(h-wSize, -1)
|
||||
v := -h - wSize
|
||||
if v < -1 {
|
||||
v = -1
|
||||
}
|
||||
d.hashPrev[i] = v
|
||||
}
|
||||
}
|
||||
count, err := d.r.Read(d.window[d.windowEnd:])
|
||||
@ -177,10 +185,18 @@ func (d *compressor) writeBlock(tokens []token, index int, eof bool) os.Error {
|
||||
// Try to find a match starting at index whose length is greater than prevSize.
|
||||
// We only look at chainCount possibilities before giving up.
|
||||
func (d *compressor) findMatch(pos int, prevHead int, prevLength int, lookahead int) (length, offset int, ok bool) {
|
||||
win := d.window[0 : pos+min(maxMatchLength, lookahead)]
|
||||
minMatchLook := maxMatchLength
|
||||
if lookahead < minMatchLook {
|
||||
minMatchLook = lookahead
|
||||
}
|
||||
|
||||
win := d.window[0 : pos+minMatchLook]
|
||||
|
||||
// We quit when we get a match that's at least nice long
|
||||
nice := min(d.niceMatch, len(win)-pos)
|
||||
nice := len(win) - pos
|
||||
if d.niceMatch < nice {
|
||||
nice = d.niceMatch
|
||||
}
|
||||
|
||||
// If we've got a match that's good enough, only look in 1/4 the chain.
|
||||
tries := d.maxChainLength
|
||||
@ -344,9 +360,12 @@ Loop:
|
||||
}
|
||||
prevLength := length
|
||||
prevOffset := offset
|
||||
minIndex := max(index-maxOffset, 0)
|
||||
length = minMatchLength - 1
|
||||
offset = 0
|
||||
minIndex := index - maxOffset
|
||||
if minIndex < 0 {
|
||||
minIndex = 0
|
||||
}
|
||||
|
||||
if chainHead >= minIndex &&
|
||||
(isFastDeflate && lookahead > minMatchLength-1 ||
|
||||
@ -477,6 +496,33 @@ func NewWriter(w io.Writer, level int) *Writer {
|
||||
return &Writer{pw, &d}
|
||||
}
|
||||
|
||||
// NewWriterDict is like NewWriter but initializes the new
|
||||
// Writer with a preset dictionary. The returned Writer behaves
|
||||
// as if the dictionary had been written to it without producing
|
||||
// any compressed output. The compressed data written to w
|
||||
// can only be decompressed by a Reader initialized with the
|
||||
// same dictionary.
|
||||
func NewWriterDict(w io.Writer, level int, dict []byte) *Writer {
|
||||
dw := &dictWriter{w, false}
|
||||
zw := NewWriter(dw, level)
|
||||
zw.Write(dict)
|
||||
zw.Flush()
|
||||
dw.enabled = true
|
||||
return zw
|
||||
}
|
||||
|
||||
type dictWriter struct {
|
||||
w io.Writer
|
||||
enabled bool
|
||||
}
|
||||
|
||||
func (w *dictWriter) Write(b []byte) (n int, err os.Error) {
|
||||
if w.enabled {
|
||||
return w.w.Write(b)
|
||||
}
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
// A Writer takes data written to it and writes the compressed
|
||||
// form of that data to an underlying writer (see NewWriter).
|
||||
type Writer struct {
|
||||
|
@ -275,3 +275,49 @@ func TestDeflateInflateString(t *testing.T) {
|
||||
}
|
||||
testToFromWithLevel(t, 1, gold, "2.718281828...")
|
||||
}
|
||||
|
||||
func TestReaderDict(t *testing.T) {
|
||||
const (
|
||||
dict = "hello world"
|
||||
text = "hello again world"
|
||||
)
|
||||
var b bytes.Buffer
|
||||
w := NewWriter(&b, 5)
|
||||
w.Write([]byte(dict))
|
||||
w.Flush()
|
||||
b.Reset()
|
||||
w.Write([]byte(text))
|
||||
w.Close()
|
||||
|
||||
r := NewReaderDict(&b, []byte(dict))
|
||||
data, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if string(data) != "hello again world" {
|
||||
t.Fatalf("read returned %q want %q", string(data), text)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriterDict(t *testing.T) {
|
||||
const (
|
||||
dict = "hello world"
|
||||
text = "hello again world"
|
||||
)
|
||||
var b bytes.Buffer
|
||||
w := NewWriter(&b, 5)
|
||||
w.Write([]byte(dict))
|
||||
w.Flush()
|
||||
b.Reset()
|
||||
w.Write([]byte(text))
|
||||
w.Close()
|
||||
|
||||
var b1 bytes.Buffer
|
||||
w = NewWriterDict(&b1, 5, []byte(dict))
|
||||
w.Write([]byte(text))
|
||||
w.Close()
|
||||
|
||||
if !bytes.Equal(b1.Bytes(), b.Bytes()) {
|
||||
t.Fatalf("writer wrote %q want %q", b1.Bytes(), b.Bytes())
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,9 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// The flate package implements the DEFLATE compressed data
|
||||
// format, described in RFC 1951. The gzip and zlib packages
|
||||
// implement access to DEFLATE-based file formats.
|
||||
// Package flate implements the DEFLATE compressed data format, described in
|
||||
// RFC 1951. The gzip and zlib packages implement access to DEFLATE-based file
|
||||
// formats.
|
||||
package flate
|
||||
|
||||
import (
|
||||
@ -526,6 +526,20 @@ func (f *decompressor) dataBlock() os.Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *decompressor) setDict(dict []byte) {
|
||||
if len(dict) > len(f.hist) {
|
||||
// Will only remember the tail.
|
||||
dict = dict[len(dict)-len(f.hist):]
|
||||
}
|
||||
|
||||
f.hp = copy(f.hist[:], dict)
|
||||
if f.hp == len(f.hist) {
|
||||
f.hp = 0
|
||||
f.hfull = true
|
||||
}
|
||||
f.hw = f.hp
|
||||
}
|
||||
|
||||
func (f *decompressor) moreBits() os.Error {
|
||||
c, err := f.r.ReadByte()
|
||||
if err != nil {
|
||||
@ -618,3 +632,16 @@ func NewReader(r io.Reader) io.ReadCloser {
|
||||
go func() { pw.CloseWithError(f.decompress(r, pw)) }()
|
||||
return pr
|
||||
}
|
||||
|
||||
// NewReaderDict is like NewReader but initializes the reader
|
||||
// with a preset dictionary. The returned Reader behaves as if
|
||||
// the uncompressed data stream started with the given dictionary,
|
||||
// which has already been read. NewReaderDict is typically used
|
||||
// to read data compressed by NewWriterDict.
|
||||
func NewReaderDict(r io.Reader, dict []byte) io.ReadCloser {
|
||||
var f decompressor
|
||||
f.setDict(dict)
|
||||
pr, pw := io.Pipe()
|
||||
go func() { pw.CloseWithError(f.decompress(r, pw)) }()
|
||||
return pr
|
||||
}
|
||||
|
@ -2,8 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// The gzip package implements reading and writing of
|
||||
// gzip format compressed files, as specified in RFC 1952.
|
||||
// Package gzip implements reading and writing of gzip format compressed files,
|
||||
// as specified in RFC 1952.
|
||||
package gzip
|
||||
|
||||
import (
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// The lzw package implements the Lempel-Ziv-Welch compressed data format,
|
||||
// Package lzw implements the Lempel-Ziv-Welch compressed data format,
|
||||
// described in T. A. Welch, ``A Technique for High-Performance Data
|
||||
// Compression'', Computer, 17(6) (June 1984), pp 8-19.
|
||||
//
|
||||
@ -165,16 +165,19 @@ func decode1(pw *io.PipeWriter, r io.ByteReader, read func(*decoder) (uint16, os
|
||||
if _, err := w.Write(buf[i:]); err != nil {
|
||||
return err
|
||||
}
|
||||
// Save what the hi code expands to.
|
||||
suffix[hi] = uint8(c)
|
||||
prefix[hi] = last
|
||||
if last != invalidCode {
|
||||
// Save what the hi code expands to.
|
||||
suffix[hi] = uint8(c)
|
||||
prefix[hi] = last
|
||||
}
|
||||
default:
|
||||
return os.NewError("lzw: invalid code")
|
||||
}
|
||||
last, hi = code, hi+1
|
||||
if hi == overflow {
|
||||
if hi >= overflow {
|
||||
if d.width == maxWidth {
|
||||
return os.NewError("lzw: missing clear code")
|
||||
last = invalidCode
|
||||
continue
|
||||
}
|
||||
d.width++
|
||||
overflow <<= 1
|
||||
|
@ -112,12 +112,6 @@ func TestReader(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
type devNull struct{}
|
||||
|
||||
func (devNull) Write(p []byte) (int, os.Error) {
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func benchmarkDecoder(b *testing.B, n int) {
|
||||
b.StopTimer()
|
||||
b.SetBytes(int64(n))
|
||||
@ -134,7 +128,7 @@ func benchmarkDecoder(b *testing.B, n int) {
|
||||
runtime.GC()
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
io.Copy(devNull{}, NewReader(bytes.NewBuffer(buf1), LSB, 8))
|
||||
io.Copy(ioutil.Discard, NewReader(bytes.NewBuffer(buf1), LSB, 8))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,7 @@ func benchmarkEncoder(b *testing.B, n int) {
|
||||
runtime.GC()
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
w := NewWriter(devNull{}, LSB, 8)
|
||||
w := NewWriter(ioutil.Discard, LSB, 8)
|
||||
w.Write(buf1)
|
||||
w.Close()
|
||||
}
|
||||
|
@ -3,8 +3,8 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
The zlib package implements reading and writing of zlib
|
||||
format compressed data, as specified in RFC 1950.
|
||||
Package zlib implements reading and writing of zlib format compressed data,
|
||||
as specified in RFC 1950.
|
||||
|
||||
The implementation provides filters that uncompress during reading
|
||||
and compress during writing. For example, to write compressed data
|
||||
@ -36,7 +36,7 @@ const zlibDeflate = 8
|
||||
|
||||
var ChecksumError os.Error = os.ErrorString("zlib checksum error")
|
||||
var HeaderError os.Error = os.ErrorString("invalid zlib header")
|
||||
var UnsupportedError os.Error = os.ErrorString("unsupported zlib format")
|
||||
var DictionaryError os.Error = os.ErrorString("invalid zlib dictionary")
|
||||
|
||||
type reader struct {
|
||||
r flate.Reader
|
||||
@ -50,6 +50,12 @@ type reader struct {
|
||||
// The implementation buffers input and may read more data than necessary from r.
|
||||
// It is the caller's responsibility to call Close on the ReadCloser when done.
|
||||
func NewReader(r io.Reader) (io.ReadCloser, os.Error) {
|
||||
return NewReaderDict(r, nil)
|
||||
}
|
||||
|
||||
// NewReaderDict is like NewReader but uses a preset dictionary.
|
||||
// NewReaderDict ignores the dictionary if the compressed data does not refer to it.
|
||||
func NewReaderDict(r io.Reader, dict []byte) (io.ReadCloser, os.Error) {
|
||||
z := new(reader)
|
||||
if fr, ok := r.(flate.Reader); ok {
|
||||
z.r = fr
|
||||
@ -65,11 +71,19 @@ func NewReader(r io.Reader) (io.ReadCloser, os.Error) {
|
||||
return nil, HeaderError
|
||||
}
|
||||
if z.scratch[1]&0x20 != 0 {
|
||||
// BUG(nigeltao): The zlib package does not implement the FDICT flag.
|
||||
return nil, UnsupportedError
|
||||
_, err = io.ReadFull(z.r, z.scratch[0:4])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3])
|
||||
if checksum != adler32.Checksum(dict) {
|
||||
return nil, DictionaryError
|
||||
}
|
||||
z.decompressor = flate.NewReaderDict(z.r, dict)
|
||||
} else {
|
||||
z.decompressor = flate.NewReader(z.r)
|
||||
}
|
||||
z.digest = adler32.New()
|
||||
z.decompressor = flate.NewReader(z.r)
|
||||
return z, nil
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@ type zlibTest struct {
|
||||
desc string
|
||||
raw string
|
||||
compressed []byte
|
||||
dict []byte
|
||||
err os.Error
|
||||
}
|
||||
|
||||
@ -27,6 +28,7 @@ var zlibTests = []zlibTest{
|
||||
"",
|
||||
[]byte{0x78, 0x9c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01},
|
||||
nil,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"goodbye",
|
||||
@ -37,23 +39,27 @@ var zlibTests = []zlibTest{
|
||||
0x01, 0x00, 0x28, 0xa5, 0x05, 0x5e,
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"bad header",
|
||||
"",
|
||||
[]byte{0x78, 0x9f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01},
|
||||
nil,
|
||||
HeaderError,
|
||||
},
|
||||
{
|
||||
"bad checksum",
|
||||
"",
|
||||
[]byte{0x78, 0x9c, 0x03, 0x00, 0x00, 0x00, 0x00, 0xff},
|
||||
nil,
|
||||
ChecksumError,
|
||||
},
|
||||
{
|
||||
"not enough data",
|
||||
"",
|
||||
[]byte{0x78, 0x9c, 0x03, 0x00, 0x00, 0x00},
|
||||
nil,
|
||||
io.ErrUnexpectedEOF,
|
||||
},
|
||||
{
|
||||
@ -64,6 +70,33 @@ var zlibTests = []zlibTest{
|
||||
0x78, 0x9c, 0xff,
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"dictionary",
|
||||
"Hello, World!\n",
|
||||
[]byte{
|
||||
0x78, 0xbb, 0x1c, 0x32, 0x04, 0x27, 0xf3, 0x00,
|
||||
0xb1, 0x75, 0x20, 0x1c, 0x45, 0x2e, 0x00, 0x24,
|
||||
0x12, 0x04, 0x74,
|
||||
},
|
||||
[]byte{
|
||||
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x0a,
|
||||
},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"wrong dictionary",
|
||||
"",
|
||||
[]byte{
|
||||
0x78, 0xbb, 0x1c, 0x32, 0x04, 0x27, 0xf3, 0x00,
|
||||
0xb1, 0x75, 0x20, 0x1c, 0x45, 0x2e, 0x00, 0x24,
|
||||
0x12, 0x04, 0x74,
|
||||
},
|
||||
[]byte{
|
||||
0x48, 0x65, 0x6c, 0x6c,
|
||||
},
|
||||
DictionaryError,
|
||||
},
|
||||
}
|
||||
|
||||
@ -71,7 +104,7 @@ func TestDecompressor(t *testing.T) {
|
||||
b := new(bytes.Buffer)
|
||||
for _, tt := range zlibTests {
|
||||
in := bytes.NewBuffer(tt.compressed)
|
||||
zlib, err := NewReader(in)
|
||||
zlib, err := NewReaderDict(in, tt.dict)
|
||||
if err != nil {
|
||||
if err != tt.err {
|
||||
t.Errorf("%s: NewReader: %s", tt.desc, err)
|
||||
|
@ -21,56 +21,80 @@ const (
|
||||
DefaultCompression = flate.DefaultCompression
|
||||
)
|
||||
|
||||
type writer struct {
|
||||
// A Writer takes data written to it and writes the compressed
|
||||
// form of that data to an underlying writer (see NewWriter).
|
||||
type Writer struct {
|
||||
w io.Writer
|
||||
compressor io.WriteCloser
|
||||
compressor *flate.Writer
|
||||
digest hash.Hash32
|
||||
err os.Error
|
||||
scratch [4]byte
|
||||
}
|
||||
|
||||
// NewWriter calls NewWriterLevel with the default compression level.
|
||||
func NewWriter(w io.Writer) (io.WriteCloser, os.Error) {
|
||||
func NewWriter(w io.Writer) (*Writer, os.Error) {
|
||||
return NewWriterLevel(w, DefaultCompression)
|
||||
}
|
||||
|
||||
// NewWriterLevel creates a new io.WriteCloser that satisfies writes by compressing data written to w.
|
||||
// NewWriterLevel calls NewWriterDict with no dictionary.
|
||||
func NewWriterLevel(w io.Writer, level int) (*Writer, os.Error) {
|
||||
return NewWriterDict(w, level, nil)
|
||||
}
|
||||
|
||||
// NewWriterDict creates a new io.WriteCloser that satisfies writes by compressing data written to w.
|
||||
// It is the caller's responsibility to call Close on the WriteCloser when done.
|
||||
// level is the compression level, which can be DefaultCompression, NoCompression,
|
||||
// or any integer value between BestSpeed and BestCompression (inclusive).
|
||||
func NewWriterLevel(w io.Writer, level int) (io.WriteCloser, os.Error) {
|
||||
z := new(writer)
|
||||
// dict is the preset dictionary to compress with, or nil to use no dictionary.
|
||||
func NewWriterDict(w io.Writer, level int, dict []byte) (*Writer, os.Error) {
|
||||
z := new(Writer)
|
||||
// ZLIB has a two-byte header (as documented in RFC 1950).
|
||||
// The first four bits is the CINFO (compression info), which is 7 for the default deflate window size.
|
||||
// The next four bits is the CM (compression method), which is 8 for deflate.
|
||||
z.scratch[0] = 0x78
|
||||
// The next two bits is the FLEVEL (compression level). The four values are:
|
||||
// 0=fastest, 1=fast, 2=default, 3=best.
|
||||
// The next bit, FDICT, is unused, in this implementation.
|
||||
// The next bit, FDICT, is set if a dictionary is given.
|
||||
// The final five FCHECK bits form a mod-31 checksum.
|
||||
switch level {
|
||||
case 0, 1:
|
||||
z.scratch[1] = 0x01
|
||||
z.scratch[1] = 0 << 6
|
||||
case 2, 3, 4, 5:
|
||||
z.scratch[1] = 0x5e
|
||||
z.scratch[1] = 1 << 6
|
||||
case 6, -1:
|
||||
z.scratch[1] = 0x9c
|
||||
z.scratch[1] = 2 << 6
|
||||
case 7, 8, 9:
|
||||
z.scratch[1] = 0xda
|
||||
z.scratch[1] = 3 << 6
|
||||
default:
|
||||
return nil, os.NewError("level out of range")
|
||||
}
|
||||
if dict != nil {
|
||||
z.scratch[1] |= 1 << 5
|
||||
}
|
||||
z.scratch[1] += uint8(31 - (uint16(z.scratch[0])<<8+uint16(z.scratch[1]))%31)
|
||||
_, err := w.Write(z.scratch[0:2])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if dict != nil {
|
||||
// The next four bytes are the Adler-32 checksum of the dictionary.
|
||||
checksum := adler32.Checksum(dict)
|
||||
z.scratch[0] = uint8(checksum >> 24)
|
||||
z.scratch[1] = uint8(checksum >> 16)
|
||||
z.scratch[2] = uint8(checksum >> 8)
|
||||
z.scratch[3] = uint8(checksum >> 0)
|
||||
_, err = w.Write(z.scratch[0:4])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
z.w = w
|
||||
z.compressor = flate.NewWriter(w, level)
|
||||
z.digest = adler32.New()
|
||||
return z, nil
|
||||
}
|
||||
|
||||
func (z *writer) Write(p []byte) (n int, err os.Error) {
|
||||
func (z *Writer) Write(p []byte) (n int, err os.Error) {
|
||||
if z.err != nil {
|
||||
return 0, z.err
|
||||
}
|
||||
@ -86,8 +110,17 @@ func (z *writer) Write(p []byte) (n int, err os.Error) {
|
||||
return
|
||||
}
|
||||
|
||||
// Flush flushes the underlying compressor.
|
||||
func (z *Writer) Flush() os.Error {
|
||||
if z.err != nil {
|
||||
return z.err
|
||||
}
|
||||
z.err = z.compressor.Flush()
|
||||
return z.err
|
||||
}
|
||||
|
||||
// Calling Close does not close the wrapped io.Writer originally passed to NewWriter.
|
||||
func (z *writer) Close() os.Error {
|
||||
func (z *Writer) Close() os.Error {
|
||||
if z.err != nil {
|
||||
return z.err
|
||||
}
|
||||
|
@ -16,13 +16,19 @@ var filenames = []string{
|
||||
"../testdata/pi.txt",
|
||||
}
|
||||
|
||||
// Tests that compressing and then decompressing the given file at the given compression level
|
||||
// Tests that compressing and then decompressing the given file at the given compression level and dictionary
|
||||
// yields equivalent bytes to the original file.
|
||||
func testFileLevel(t *testing.T, fn string, level int) {
|
||||
func testFileLevelDict(t *testing.T, fn string, level int, d string) {
|
||||
// Read dictionary, if given.
|
||||
var dict []byte
|
||||
if d != "" {
|
||||
dict = []byte(d)
|
||||
}
|
||||
|
||||
// Read the file, as golden output.
|
||||
golden, err := os.Open(fn)
|
||||
if err != nil {
|
||||
t.Errorf("%s (level=%d): %v", fn, level, err)
|
||||
t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
|
||||
return
|
||||
}
|
||||
defer golden.Close()
|
||||
@ -30,7 +36,7 @@ func testFileLevel(t *testing.T, fn string, level int) {
|
||||
// Read the file again, and push it through a pipe that compresses at the write end, and decompresses at the read end.
|
||||
raw, err := os.Open(fn)
|
||||
if err != nil {
|
||||
t.Errorf("%s (level=%d): %v", fn, level, err)
|
||||
t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
|
||||
return
|
||||
}
|
||||
piper, pipew := io.Pipe()
|
||||
@ -38,9 +44,9 @@ func testFileLevel(t *testing.T, fn string, level int) {
|
||||
go func() {
|
||||
defer raw.Close()
|
||||
defer pipew.Close()
|
||||
zlibw, err := NewWriterLevel(pipew, level)
|
||||
zlibw, err := NewWriterDict(pipew, level, dict)
|
||||
if err != nil {
|
||||
t.Errorf("%s (level=%d): %v", fn, level, err)
|
||||
t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
|
||||
return
|
||||
}
|
||||
defer zlibw.Close()
|
||||
@ -48,7 +54,7 @@ func testFileLevel(t *testing.T, fn string, level int) {
|
||||
for {
|
||||
n, err0 := raw.Read(b[0:])
|
||||
if err0 != nil && err0 != os.EOF {
|
||||
t.Errorf("%s (level=%d): %v", fn, level, err0)
|
||||
t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err0)
|
||||
return
|
||||
}
|
||||
_, err1 := zlibw.Write(b[0:n])
|
||||
@ -57,7 +63,7 @@ func testFileLevel(t *testing.T, fn string, level int) {
|
||||
return
|
||||
}
|
||||
if err1 != nil {
|
||||
t.Errorf("%s (level=%d): %v", fn, level, err1)
|
||||
t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err1)
|
||||
return
|
||||
}
|
||||
if err0 == os.EOF {
|
||||
@ -65,9 +71,9 @@ func testFileLevel(t *testing.T, fn string, level int) {
|
||||
}
|
||||
}
|
||||
}()
|
||||
zlibr, err := NewReader(piper)
|
||||
zlibr, err := NewReaderDict(piper, dict)
|
||||
if err != nil {
|
||||
t.Errorf("%s (level=%d): %v", fn, level, err)
|
||||
t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err)
|
||||
return
|
||||
}
|
||||
defer zlibr.Close()
|
||||
@ -76,20 +82,20 @@ func testFileLevel(t *testing.T, fn string, level int) {
|
||||
b0, err0 := ioutil.ReadAll(golden)
|
||||
b1, err1 := ioutil.ReadAll(zlibr)
|
||||
if err0 != nil {
|
||||
t.Errorf("%s (level=%d): %v", fn, level, err0)
|
||||
t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err0)
|
||||
return
|
||||
}
|
||||
if err1 != nil {
|
||||
t.Errorf("%s (level=%d): %v", fn, level, err1)
|
||||
t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err1)
|
||||
return
|
||||
}
|
||||
if len(b0) != len(b1) {
|
||||
t.Errorf("%s (level=%d): length mismatch %d versus %d", fn, level, len(b0), len(b1))
|
||||
t.Errorf("%s (level=%d, dict=%q): length mismatch %d versus %d", fn, level, d, len(b0), len(b1))
|
||||
return
|
||||
}
|
||||
for i := 0; i < len(b0); i++ {
|
||||
if b0[i] != b1[i] {
|
||||
t.Errorf("%s (level=%d): mismatch at %d, 0x%02x versus 0x%02x\n", fn, level, i, b0[i], b1[i])
|
||||
t.Errorf("%s (level=%d, dict=%q): mismatch at %d, 0x%02x versus 0x%02x\n", fn, level, d, i, b0[i], b1[i])
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -97,10 +103,21 @@ func testFileLevel(t *testing.T, fn string, level int) {
|
||||
|
||||
func TestWriter(t *testing.T) {
|
||||
for _, fn := range filenames {
|
||||
testFileLevel(t, fn, DefaultCompression)
|
||||
testFileLevel(t, fn, NoCompression)
|
||||
testFileLevelDict(t, fn, DefaultCompression, "")
|
||||
testFileLevelDict(t, fn, NoCompression, "")
|
||||
for level := BestSpeed; level <= BestCompression; level++ {
|
||||
testFileLevel(t, fn, level)
|
||||
testFileLevelDict(t, fn, level, "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriterDict(t *testing.T) {
|
||||
const dictionary = "0123456789."
|
||||
for _, fn := range filenames {
|
||||
testFileLevelDict(t, fn, DefaultCompression, dictionary)
|
||||
testFileLevelDict(t, fn, NoCompression, dictionary)
|
||||
for level := BestSpeed; level <= BestCompression; level++ {
|
||||
testFileLevelDict(t, fn, level, dictionary)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This package provides heap operations for any type that implements
|
||||
// Package heap provides heap operations for any type that implements
|
||||
// heap.Interface.
|
||||
//
|
||||
package heap
|
||||
|
@ -2,11 +2,12 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package heap
|
||||
package heap_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"container/vector"
|
||||
. "container/heap"
|
||||
)
|
||||
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// The list package implements a doubly linked list.
|
||||
// Package list implements a doubly linked list.
|
||||
//
|
||||
// To iterate over a list (where l is a *List):
|
||||
// for e := l.Front(); e != nil; e = e.Next() {
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// The ring package implements operations on circular lists.
|
||||
// Package ring implements operations on circular lists.
|
||||
package ring
|
||||
|
||||
// A Ring is an element of a circular list, or ring.
|
||||
|
@ -2,8 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// The vector package implements containers for managing sequences
|
||||
// of elements. Vectors grow and shrink dynamically as necessary.
|
||||
// Package vector implements containers for managing sequences of elements.
|
||||
// Vectors grow and shrink dynamically as necessary.
|
||||
package vector
|
||||
|
||||
|
||||
|
@ -2,12 +2,12 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// AES constants - 8720 bytes of initialized data.
|
||||
|
||||
// This package implements AES encryption (formerly Rijndael),
|
||||
// as defined in U.S. Federal Information Processing Standards Publication 197.
|
||||
// Package aes implements AES encryption (formerly Rijndael), as defined in
|
||||
// U.S. Federal Information Processing Standards Publication 197.
|
||||
package aes
|
||||
|
||||
// This file contains AES constants - 8720 bytes of initialized data.
|
||||
|
||||
// http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
||||
|
||||
// AES is based on the mathematical behavior of binary polynomials
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This package implements Bruce Schneier's Blowfish encryption algorithm.
|
||||
// Package blowfish implements Bruce Schneier's Blowfish encryption algorithm.
|
||||
package blowfish
|
||||
|
||||
// The code is a port of Bruce Schneier's C implementation.
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This package implements CAST5, as defined in RFC 2144. CAST5 is a common
|
||||
// Package cast5 implements CAST5, as defined in RFC 2144. CAST5 is a common
|
||||
// OpenPGP cipher.
|
||||
package cast5
|
||||
|
||||
|
@ -2,8 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// The cipher package implements standard block cipher modes
|
||||
// that can be wrapped around low-level block cipher implementations.
|
||||
// Package cipher implements standard block cipher modes that can be wrapped
|
||||
// around low-level block cipher implementations.
|
||||
// See http://csrc.nist.gov/groups/ST/toolkit/BCM/current_modes.html
|
||||
// and NIST Special Publication 800-38A.
|
||||
package cipher
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// The crypto package collects common cryptographic constants.
|
||||
// Package crypto collects common cryptographic constants.
|
||||
package crypto
|
||||
|
||||
import (
|
||||
|
@ -2,8 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// The elliptic package implements several standard elliptic curves over prime
|
||||
// fields
|
||||
// Package elliptic implements several standard elliptic curves over prime
|
||||
// fields.
|
||||
package elliptic
|
||||
|
||||
// This package operates, internally, on Jacobian coordinates. For a given
|
||||
|
@ -2,8 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// The hmac package implements the Keyed-Hash Message Authentication Code (HMAC)
|
||||
// as defined in U.S. Federal Information Processing Standards Publication 198.
|
||||
// Package hmac implements the Keyed-Hash Message Authentication Code (HMAC) as
|
||||
// defined in U.S. Federal Information Processing Standards Publication 198.
|
||||
// An HMAC is a cryptographic hash that uses a key to sign a message.
|
||||
// The receiver verifies the hash by recomputing it using the same key.
|
||||
package hmac
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This package implements the MD4 hash algorithm as defined in RFC 1320.
|
||||
// Package md4 implements the MD4 hash algorithm as defined in RFC 1320.
|
||||
package md4
|
||||
|
||||
import (
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This package implements the MD5 hash algorithm as defined in RFC 1321.
|
||||
// Package md5 implements the MD5 hash algorithm as defined in RFC 1321.
|
||||
package md5
|
||||
|
||||
import (
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This package parses OCSP responses as specified in RFC 2560. OCSP responses
|
||||
// Package ocsp parses OCSP responses as specified in RFC 2560. OCSP responses
|
||||
// are signed messages attesting to the validity of a certificate for a small
|
||||
// period of time. This is used to manage revocation for X.509 certificates.
|
||||
package ocsp
|
||||
|
@ -2,15 +2,15 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This package implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is
|
||||
// Package armor implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is
|
||||
// very similar to PEM except that it has an additional CRC checksum.
|
||||
package armor
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"crypto/openpgp/error"
|
||||
"encoding/base64"
|
||||
"encoding/line"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
@ -63,7 +63,7 @@ var armorEndOfLine = []byte("-----")
|
||||
// lineReader wraps a line based reader. It watches for the end of an armor
|
||||
// block and records the expected CRC value.
|
||||
type lineReader struct {
|
||||
in *line.Reader
|
||||
in *bufio.Reader
|
||||
buf []byte
|
||||
eof bool
|
||||
crc uint32
|
||||
@ -156,7 +156,7 @@ func (r *openpgpReader) Read(p []byte) (n int, err os.Error) {
|
||||
// given Reader is not usable after calling this function: an arbitary amount
|
||||
// of data may have been read past the end of the block.
|
||||
func Decode(in io.Reader) (p *Block, err os.Error) {
|
||||
r := line.NewReader(in, 100)
|
||||
r, _ := bufio.NewReaderSize(in, 100)
|
||||
var line []byte
|
||||
ignoreNext := false
|
||||
|
||||
|
@ -18,9 +18,9 @@ var armorEndOfLineOut = []byte("-----\n")
|
||||
// writeSlices writes its arguments to the given Writer.
|
||||
func writeSlices(out io.Writer, slices ...[]byte) (err os.Error) {
|
||||
for _, s := range slices {
|
||||
_, err := out.Write(s)
|
||||
_, err = out.Write(s)
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
}
|
||||
return
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This package contains common error types for the OpenPGP packages.
|
||||
// Package error contains common error types for the OpenPGP packages.
|
||||
package error
|
||||
|
||||
import (
|
||||
|
@ -5,6 +5,7 @@
|
||||
package openpgp
|
||||
|
||||
import (
|
||||
"crypto/openpgp/armor"
|
||||
"crypto/openpgp/error"
|
||||
"crypto/openpgp/packet"
|
||||
"io"
|
||||
@ -13,6 +14,8 @@ import (
|
||||
|
||||
// PublicKeyType is the armor type for a PGP public key.
|
||||
var PublicKeyType = "PGP PUBLIC KEY BLOCK"
|
||||
// PrivateKeyType is the armor type for a PGP private key.
|
||||
var PrivateKeyType = "PGP PRIVATE KEY BLOCK"
|
||||
|
||||
// An Entity represents the components of an OpenPGP key: a primary public key
|
||||
// (which must be a signing key), one or more identities claimed by that key,
|
||||
@ -101,37 +104,50 @@ func (el EntityList) DecryptionKeys() (keys []Key) {
|
||||
|
||||
// ReadArmoredKeyRing reads one or more public/private keys from an armor keyring file.
|
||||
func ReadArmoredKeyRing(r io.Reader) (EntityList, os.Error) {
|
||||
body, err := readArmored(r, PublicKeyType)
|
||||
block, err := armor.Decode(r)
|
||||
if err == os.EOF {
|
||||
return nil, error.InvalidArgumentError("no armored data found")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if block.Type != PublicKeyType && block.Type != PrivateKeyType {
|
||||
return nil, error.InvalidArgumentError("expected public or private key block, got: " + block.Type)
|
||||
}
|
||||
|
||||
return ReadKeyRing(body)
|
||||
return ReadKeyRing(block.Body)
|
||||
}
|
||||
|
||||
// ReadKeyRing reads one or more public/private keys, ignoring unsupported keys.
|
||||
// ReadKeyRing reads one or more public/private keys. Unsupported keys are
|
||||
// ignored as long as at least a single valid key is found.
|
||||
func ReadKeyRing(r io.Reader) (el EntityList, err os.Error) {
|
||||
packets := packet.NewReader(r)
|
||||
var lastUnsupportedError os.Error
|
||||
|
||||
for {
|
||||
var e *Entity
|
||||
e, err = readEntity(packets)
|
||||
if err != nil {
|
||||
if _, ok := err.(error.UnsupportedError); ok {
|
||||
lastUnsupportedError = err
|
||||
err = readToNextPublicKey(packets)
|
||||
}
|
||||
if err == os.EOF {
|
||||
err = nil
|
||||
return
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
el = nil
|
||||
return
|
||||
break
|
||||
}
|
||||
} else {
|
||||
el = append(el, e)
|
||||
}
|
||||
}
|
||||
|
||||
if len(el) == 0 && err == nil {
|
||||
err = lastUnsupportedError
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -197,25 +213,28 @@ EachPacket:
|
||||
current.Name = pkt.Id
|
||||
current.UserId = pkt
|
||||
e.Identities[pkt.Id] = current
|
||||
p, err = packets.Next()
|
||||
if err == os.EOF {
|
||||
err = io.ErrUnexpectedEOF
|
||||
}
|
||||
if err != nil {
|
||||
if _, ok := err.(error.UnsupportedError); ok {
|
||||
|
||||
for {
|
||||
p, err = packets.Next()
|
||||
if err == os.EOF {
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, error.StructuralError("identity self-signature invalid: " + err.String())
|
||||
}
|
||||
current.SelfSignature, ok = p.(*packet.Signature)
|
||||
if !ok {
|
||||
return nil, error.StructuralError("user ID packet not followed by self signature")
|
||||
}
|
||||
if current.SelfSignature.SigType != packet.SigTypePositiveCert {
|
||||
return nil, error.StructuralError("user ID self-signature with wrong type")
|
||||
}
|
||||
if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, current.SelfSignature); err != nil {
|
||||
return nil, error.StructuralError("user ID self-signature invalid: " + err.String())
|
||||
|
||||
sig, ok := p.(*packet.Signature)
|
||||
if !ok {
|
||||
return nil, error.StructuralError("user ID packet not followed by self-signature")
|
||||
}
|
||||
|
||||
if sig.SigType == packet.SigTypePositiveCert && sig.IssuerKeyId != nil && *sig.IssuerKeyId == e.PrimaryKey.KeyId {
|
||||
if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, sig); err != nil {
|
||||
return nil, error.StructuralError("user ID self-signature invalid: " + err.String())
|
||||
}
|
||||
current.SelfSignature = sig
|
||||
break
|
||||
}
|
||||
current.Signatures = append(current.Signatures, sig)
|
||||
}
|
||||
case *packet.Signature:
|
||||
if current == nil {
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This package implements parsing and serialisation of OpenPGP packets, as
|
||||
// Package packet implements parsing and serialisation of OpenPGP packets, as
|
||||
// specified in RFC 4880.
|
||||
package packet
|
||||
|
||||
|
@ -164,8 +164,10 @@ func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err os.Error) {
|
||||
}
|
||||
|
||||
rsaPriv.D = new(big.Int).SetBytes(d)
|
||||
rsaPriv.P = new(big.Int).SetBytes(p)
|
||||
rsaPriv.Q = new(big.Int).SetBytes(q)
|
||||
rsaPriv.Primes = make([]*big.Int, 2)
|
||||
rsaPriv.Primes[0] = new(big.Int).SetBytes(p)
|
||||
rsaPriv.Primes[1] = new(big.Int).SetBytes(q)
|
||||
rsaPriv.Precompute()
|
||||
pk.PrivateKey = rsaPriv
|
||||
pk.Encrypted = false
|
||||
pk.encryptedData = nil
|
||||
|
@ -15,6 +15,7 @@ import (
|
||||
"hash"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2.
|
||||
@ -47,7 +48,7 @@ func (pk *PublicKey) parse(r io.Reader) (err os.Error) {
|
||||
case PubKeyAlgoDSA:
|
||||
err = pk.parseDSA(r)
|
||||
default:
|
||||
err = error.UnsupportedError("public key type")
|
||||
err = error.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This openpgp package implements high level operations on OpenPGP messages.
|
||||
// Package openpgp implements high level operations on OpenPGP messages.
|
||||
package openpgp
|
||||
|
||||
import (
|
||||
|
@ -230,6 +230,23 @@ func TestDetachedSignatureDSA(t *testing.T) {
|
||||
testDetachedSignature(t, kring, readerFromHex(detachedSignatureDSAHex), signedInput, "binary", testKey3KeyId)
|
||||
}
|
||||
|
||||
func TestReadingArmoredPrivateKey(t *testing.T) {
|
||||
el, err := ReadArmoredKeyRing(bytes.NewBufferString(armoredPrivateKeyBlock))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if len(el) != 1 {
|
||||
t.Errorf("got %d entities, wanted 1\n", len(el))
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoArmoredData(t *testing.T) {
|
||||
_, err := ReadArmoredKeyRing(bytes.NewBufferString("foo"))
|
||||
if _, ok := err.(error.InvalidArgumentError); !ok {
|
||||
t.Errorf("error was not an InvalidArgumentError: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
const testKey1KeyId = 0xA34D7E18C20C31BB
|
||||
const testKey3KeyId = 0x338934250CCC0360
|
||||
|
||||
@ -259,3 +276,37 @@ const symmetricallyEncryptedCompressedHex = "8c0d04030302eb4a03808145d0d260c92f7
|
||||
const dsaTestKeyHex = "9901a2044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794"
|
||||
|
||||
const dsaTestKeyPrivateHex = "9501bb044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4d00009f592e0619d823953577d4503061706843317e4fee083db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794"
|
||||
|
||||
const armoredPrivateKeyBlock = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||
Version: GnuPG v1.4.10 (GNU/Linux)
|
||||
|
||||
lQHYBE2rFNoBBADFwqWQIW/DSqcB4yCQqnAFTJ27qS5AnB46ccAdw3u4Greeu3Bp
|
||||
idpoHdjULy7zSKlwR1EA873dO/k/e11Ml3dlAFUinWeejWaK2ugFP6JjiieSsrKn
|
||||
vWNicdCS4HTWn0X4sjl0ZiAygw6GNhqEQ3cpLeL0g8E9hnYzJKQ0LWJa0QARAQAB
|
||||
AAP/TB81EIo2VYNmTq0pK1ZXwUpxCrvAAIG3hwKjEzHcbQznsjNvPUihZ+NZQ6+X
|
||||
0HCfPAdPkGDCLCb6NavcSW+iNnLTrdDnSI6+3BbIONqWWdRDYJhqZCkqmG6zqSfL
|
||||
IdkJgCw94taUg5BWP/AAeQrhzjChvpMQTVKQL5mnuZbUCeMCAN5qrYMP2S9iKdnk
|
||||
VANIFj7656ARKt/nf4CBzxcpHTyB8+d2CtPDKCmlJP6vL8t58Jmih+kHJMvC0dzn
|
||||
gr5f5+sCAOOe5gt9e0am7AvQWhdbHVfJU0TQJx+m2OiCJAqGTB1nvtBLHdJnfdC9
|
||||
TnXXQ6ZXibqLyBies/xeY2sCKL5qtTMCAKnX9+9d/5yQxRyrQUHt1NYhaXZnJbHx
|
||||
q4ytu0eWz+5i68IYUSK69jJ1NWPM0T6SkqpB3KCAIv68VFm9PxqG1KmhSrQIVGVz
|
||||
dCBLZXmIuAQTAQIAIgUCTasU2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA
|
||||
CgkQO9o98PRieSoLhgQAkLEZex02Qt7vGhZzMwuN0R22w3VwyYyjBx+fM3JFETy1
|
||||
ut4xcLJoJfIaF5ZS38UplgakHG0FQ+b49i8dMij0aZmDqGxrew1m4kBfjXw9B/v+
|
||||
eIqpODryb6cOSwyQFH0lQkXC040pjq9YqDsO5w0WYNXYKDnzRV0p4H1pweo2VDid
|
||||
AdgETasU2gEEAN46UPeWRqKHvA99arOxee38fBt2CI08iiWyI8T3J6ivtFGixSqV
|
||||
bRcPxYO/qLpVe5l84Nb3X71GfVXlc9hyv7CD6tcowL59hg1E/DC5ydI8K8iEpUmK
|
||||
/UnHdIY5h8/kqgGxkY/T/hgp5fRQgW1ZoZxLajVlMRZ8W4tFtT0DeA+JABEBAAEA
|
||||
A/0bE1jaaZKj6ndqcw86jd+QtD1SF+Cf21CWRNeLKnUds4FRRvclzTyUMuWPkUeX
|
||||
TaNNsUOFqBsf6QQ2oHUBBK4VCHffHCW4ZEX2cd6umz7mpHW6XzN4DECEzOVksXtc
|
||||
lUC1j4UB91DC/RNQqwX1IV2QLSwssVotPMPqhOi0ZLNY7wIA3n7DWKInxYZZ4K+6
|
||||
rQ+POsz6brEoRHwr8x6XlHenq1Oki855pSa1yXIARoTrSJkBtn5oI+f8AzrnN0BN
|
||||
oyeQAwIA/7E++3HDi5aweWrViiul9cd3rcsS0dEnksPhvS0ozCJiHsq/6GFmy7J8
|
||||
QSHZPteedBnZyNp5jR+H7cIfVN3KgwH/Skq4PsuPhDq5TKK6i8Pc1WW8MA6DXTdU
|
||||
nLkX7RGmMwjC0DBf7KWAlPjFaONAX3a8ndnz//fy1q7u2l9AZwrj1qa1iJ8EGAEC
|
||||
AAkFAk2rFNoCGwwACgkQO9o98PRieSo2/QP/WTzr4ioINVsvN1akKuekmEMI3LAp
|
||||
BfHwatufxxP1U+3Si/6YIk7kuPB9Hs+pRqCXzbvPRrI8NHZBmc8qIGthishdCYad
|
||||
AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL
|
||||
VrM0m72/jnpKo04=
|
||||
=zNCn
|
||||
-----END PGP PRIVATE KEY BLOCK-----`
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This package implements the various OpenPGP string-to-key transforms as
|
||||
// Package s2k implements the various OpenPGP string-to-key transforms as
|
||||
// specified in RFC 4800 section 3.7.1.
|
||||
package s2k
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This package implements RC4 encryption, as defined in Bruce Schneier's
|
||||
// Package rc4 implements RC4 encryption, as defined in Bruce Schneier's
|
||||
// Applied Cryptography.
|
||||
package rc4
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This package implements the RIPEMD-160 hash algorithm.
|
||||
// Package ripemd160 implements the RIPEMD-160 hash algorithm.
|
||||
package ripemd160
|
||||
|
||||
// RIPEMD-160 is designed by by Hans Dobbertin, Antoon Bosselaers, and Bart
|
||||
|
@ -149,10 +149,10 @@ func nonZeroRandomBytes(s []byte, rand io.Reader) (err os.Error) {
|
||||
// precompute a prefix of the digest value that makes a valid ASN1 DER string
|
||||
// with the correct contents.
|
||||
var hashPrefixes = map[crypto.Hash][]byte{
|
||||
crypto.MD5: []byte{0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10},
|
||||
crypto.SHA1: []byte{0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14},
|
||||
crypto.SHA256: []byte{0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20},
|
||||
crypto.SHA384: []byte{0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30},
|
||||
crypto.MD5: {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10},
|
||||
crypto.SHA1: {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14},
|
||||
crypto.SHA256: {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20},
|
||||
crypto.SHA384: {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30},
|
||||
crypto.SHA512: {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40},
|
||||
crypto.MD5SHA1: {}, // A special TLS case which doesn't use an ASN1 prefix.
|
||||
crypto.RIPEMD160: {0x30, 0x20, 0x30, 0x08, 0x06, 0x06, 0x28, 0xcf, 0x06, 0x03, 0x00, 0x31, 0x04, 0x14},
|
||||
|
@ -197,12 +197,6 @@ func TestVerifyPKCS1v15(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func bigFromString(s string) *big.Int {
|
||||
ret := new(big.Int)
|
||||
ret.SetString(s, 10)
|
||||
return ret
|
||||
}
|
||||
|
||||
// In order to generate new test vectors you'll need the PEM form of this key:
|
||||
// -----BEGIN RSA PRIVATE KEY-----
|
||||
// MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0
|
||||
@ -216,10 +210,12 @@ func bigFromString(s string) *big.Int {
|
||||
|
||||
var rsaPrivateKey = &PrivateKey{
|
||||
PublicKey: PublicKey{
|
||||
N: bigFromString("9353930466774385905609975137998169297361893554149986716853295022578535724979677252958524466350471210367835187480748268864277464700638583474144061408845077"),
|
||||
N: fromBase10("9353930466774385905609975137998169297361893554149986716853295022578535724979677252958524466350471210367835187480748268864277464700638583474144061408845077"),
|
||||
E: 65537,
|
||||
},
|
||||
D: bigFromString("7266398431328116344057699379749222532279343923819063639497049039389899328538543087657733766554155839834519529439851673014800261285757759040931985506583861"),
|
||||
P: bigFromString("98920366548084643601728869055592650835572950932266967461790948584315647051443"),
|
||||
Q: bigFromString("94560208308847015747498523884063394671606671904944666360068158221458669711639"),
|
||||
D: fromBase10("7266398431328116344057699379749222532279343923819063639497049039389899328538543087657733766554155839834519529439851673014800261285757759040931985506583861"),
|
||||
Primes: []*big.Int{
|
||||
fromBase10("98920366548084643601728869055592650835572950932266967461790948584315647051443"),
|
||||
fromBase10("94560208308847015747498523884063394671606671904944666360068158221458669711639"),
|
||||
},
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This package implements RSA encryption as specified in PKCS#1.
|
||||
// Package rsa implements RSA encryption as specified in PKCS#1.
|
||||
package rsa
|
||||
|
||||
// TODO(agl): Add support for PSS padding.
|
||||
@ -13,7 +13,6 @@ import (
|
||||
"hash"
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var bigZero = big.NewInt(0)
|
||||
@ -90,50 +89,60 @@ type PublicKey struct {
|
||||
|
||||
// A PrivateKey represents an RSA key
|
||||
type PrivateKey struct {
|
||||
PublicKey // public part.
|
||||
D *big.Int // private exponent
|
||||
P, Q, R *big.Int // prime factors of N (R may be nil)
|
||||
PublicKey // public part.
|
||||
D *big.Int // private exponent
|
||||
Primes []*big.Int // prime factors of N, has >= 2 elements.
|
||||
|
||||
rwMutex sync.RWMutex // protects the following
|
||||
dP, dQ, dR *big.Int // D mod (P-1) (or mod Q-1 etc)
|
||||
qInv *big.Int // q^-1 mod p
|
||||
pq *big.Int // P*Q
|
||||
tr *big.Int // pq·tr ≡ 1 mod r
|
||||
// Precomputed contains precomputed values that speed up private
|
||||
// operations, if availible.
|
||||
Precomputed PrecomputedValues
|
||||
}
|
||||
|
||||
type PrecomputedValues struct {
|
||||
Dp, Dq *big.Int // D mod (P-1) (or mod Q-1)
|
||||
Qinv *big.Int // Q^-1 mod Q
|
||||
|
||||
// CRTValues is used for the 3rd and subsequent primes. Due to a
|
||||
// historical accident, the CRT for the first two primes is handled
|
||||
// differently in PKCS#1 and interoperability is sufficiently
|
||||
// important that we mirror this.
|
||||
CRTValues []CRTValue
|
||||
}
|
||||
|
||||
// CRTValue contains the precomputed chinese remainder theorem values.
|
||||
type CRTValue struct {
|
||||
Exp *big.Int // D mod (prime-1).
|
||||
Coeff *big.Int // R·Coeff ≡ 1 mod Prime.
|
||||
R *big.Int // product of primes prior to this (inc p and q).
|
||||
}
|
||||
|
||||
// Validate performs basic sanity checks on the key.
|
||||
// It returns nil if the key is valid, or else an os.Error describing a problem.
|
||||
|
||||
func (priv *PrivateKey) Validate() os.Error {
|
||||
// Check that p, q and, maybe, r are prime. Note that this is just a
|
||||
// sanity check. Since the random witnesses chosen by ProbablyPrime are
|
||||
// deterministic, given the candidate number, it's easy for an attack
|
||||
// to generate composites that pass this test.
|
||||
if !big.ProbablyPrime(priv.P, 20) {
|
||||
return os.ErrorString("P is composite")
|
||||
}
|
||||
if !big.ProbablyPrime(priv.Q, 20) {
|
||||
return os.ErrorString("Q is composite")
|
||||
}
|
||||
if priv.R != nil && !big.ProbablyPrime(priv.R, 20) {
|
||||
return os.ErrorString("R is composite")
|
||||
// Check that the prime factors are actually prime. Note that this is
|
||||
// just a sanity check. Since the random witnesses chosen by
|
||||
// ProbablyPrime are deterministic, given the candidate number, it's
|
||||
// easy for an attack to generate composites that pass this test.
|
||||
for _, prime := range priv.Primes {
|
||||
if !big.ProbablyPrime(prime, 20) {
|
||||
return os.ErrorString("Prime factor is composite")
|
||||
}
|
||||
}
|
||||
|
||||
// Check that p*q*r == n.
|
||||
modulus := new(big.Int).Mul(priv.P, priv.Q)
|
||||
if priv.R != nil {
|
||||
modulus.Mul(modulus, priv.R)
|
||||
// Check that Πprimes == n.
|
||||
modulus := new(big.Int).Set(bigOne)
|
||||
for _, prime := range priv.Primes {
|
||||
modulus.Mul(modulus, prime)
|
||||
}
|
||||
if modulus.Cmp(priv.N) != 0 {
|
||||
return os.ErrorString("invalid modulus")
|
||||
}
|
||||
// Check that e and totient(p, q, r) are coprime.
|
||||
pminus1 := new(big.Int).Sub(priv.P, bigOne)
|
||||
qminus1 := new(big.Int).Sub(priv.Q, bigOne)
|
||||
totient := new(big.Int).Mul(pminus1, qminus1)
|
||||
if priv.R != nil {
|
||||
rminus1 := new(big.Int).Sub(priv.R, bigOne)
|
||||
totient.Mul(totient, rminus1)
|
||||
// Check that e and totient(Πprimes) are coprime.
|
||||
totient := new(big.Int).Set(bigOne)
|
||||
for _, prime := range priv.Primes {
|
||||
pminus1 := new(big.Int).Sub(prime, bigOne)
|
||||
totient.Mul(totient, pminus1)
|
||||
}
|
||||
e := big.NewInt(int64(priv.E))
|
||||
gcd := new(big.Int)
|
||||
@ -143,7 +152,7 @@ func (priv *PrivateKey) Validate() os.Error {
|
||||
if gcd.Cmp(bigOne) != 0 {
|
||||
return os.ErrorString("invalid public exponent E")
|
||||
}
|
||||
// Check that de ≡ 1 (mod totient(p, q, r))
|
||||
// Check that de ≡ 1 (mod totient(Πprimes))
|
||||
de := new(big.Int).Mul(priv.D, e)
|
||||
de.Mod(de, totient)
|
||||
if de.Cmp(bigOne) != 0 {
|
||||
@ -154,6 +163,20 @@ func (priv *PrivateKey) Validate() os.Error {
|
||||
|
||||
// GenerateKey generates an RSA keypair of the given bit size.
|
||||
func GenerateKey(rand io.Reader, bits int) (priv *PrivateKey, err os.Error) {
|
||||
return GenerateMultiPrimeKey(rand, 2, bits)
|
||||
}
|
||||
|
||||
// GenerateMultiPrimeKey generates a multi-prime RSA keypair of the given bit
|
||||
// size, as suggested in [1]. Although the public keys are compatible
|
||||
// (actually, indistinguishable) from the 2-prime case, the private keys are
|
||||
// not. Thus it may not be possible to export multi-prime private keys in
|
||||
// certain formats or to subsequently import them into other code.
|
||||
//
|
||||
// Table 1 in [2] suggests maximum numbers of primes for a given size.
|
||||
//
|
||||
// [1] US patent 4405829 (1972, expired)
|
||||
// [2] http://www.cacr.math.uwaterloo.ca/techreports/2006/cacr2006-16.pdf
|
||||
func GenerateMultiPrimeKey(rand io.Reader, nprimes int, bits int) (priv *PrivateKey, err os.Error) {
|
||||
priv = new(PrivateKey)
|
||||
// Smaller public exponents lead to faster public key
|
||||
// operations. Since the exponent must be coprime to
|
||||
@ -165,30 +188,41 @@ func GenerateKey(rand io.Reader, bits int) (priv *PrivateKey, err os.Error) {
|
||||
// [1] http://marc.info/?l=cryptography&m=115694833312008&w=2
|
||||
priv.E = 3
|
||||
|
||||
pminus1 := new(big.Int)
|
||||
qminus1 := new(big.Int)
|
||||
totient := new(big.Int)
|
||||
if nprimes < 2 {
|
||||
return nil, os.ErrorString("rsa.GenerateMultiPrimeKey: nprimes must be >= 2")
|
||||
}
|
||||
|
||||
primes := make([]*big.Int, nprimes)
|
||||
|
||||
NextSetOfPrimes:
|
||||
for {
|
||||
p, err := randomPrime(rand, bits/2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
todo := bits
|
||||
for i := 0; i < nprimes; i++ {
|
||||
primes[i], err = randomPrime(rand, todo/(nprimes-i))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
todo -= primes[i].BitLen()
|
||||
}
|
||||
|
||||
q, err := randomPrime(rand, bits/2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// Make sure that primes is pairwise unequal.
|
||||
for i, prime := range primes {
|
||||
for j := 0; j < i; j++ {
|
||||
if prime.Cmp(primes[j]) == 0 {
|
||||
continue NextSetOfPrimes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if p.Cmp(q) == 0 {
|
||||
continue
|
||||
n := new(big.Int).Set(bigOne)
|
||||
totient := new(big.Int).Set(bigOne)
|
||||
pminus1 := new(big.Int)
|
||||
for _, prime := range primes {
|
||||
n.Mul(n, prime)
|
||||
pminus1.Sub(prime, bigOne)
|
||||
totient.Mul(totient, pminus1)
|
||||
}
|
||||
|
||||
n := new(big.Int).Mul(p, q)
|
||||
pminus1.Sub(p, bigOne)
|
||||
qminus1.Sub(q, bigOne)
|
||||
totient.Mul(pminus1, qminus1)
|
||||
|
||||
g := new(big.Int)
|
||||
priv.D = new(big.Int)
|
||||
y := new(big.Int)
|
||||
@ -197,85 +231,14 @@ func GenerateKey(rand io.Reader, bits int) (priv *PrivateKey, err os.Error) {
|
||||
|
||||
if g.Cmp(bigOne) == 0 {
|
||||
priv.D.Add(priv.D, totient)
|
||||
priv.P = p
|
||||
priv.Q = q
|
||||
priv.N = n
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Generate3PrimeKey generates a 3-prime RSA keypair of the given bit size, as
|
||||
// suggested in [1]. Although the public keys are compatible (actually,
|
||||
// indistinguishable) from the 2-prime case, the private keys are not. Thus it
|
||||
// may not be possible to export 3-prime private keys in certain formats or to
|
||||
// subsequently import them into other code.
|
||||
//
|
||||
// Table 1 in [2] suggests that size should be >= 1024 when using 3 primes.
|
||||
//
|
||||
// [1] US patent 4405829 (1972, expired)
|
||||
// [2] http://www.cacr.math.uwaterloo.ca/techreports/2006/cacr2006-16.pdf
|
||||
func Generate3PrimeKey(rand io.Reader, bits int) (priv *PrivateKey, err os.Error) {
|
||||
priv = new(PrivateKey)
|
||||
priv.E = 3
|
||||
|
||||
pminus1 := new(big.Int)
|
||||
qminus1 := new(big.Int)
|
||||
rminus1 := new(big.Int)
|
||||
totient := new(big.Int)
|
||||
|
||||
for {
|
||||
p, err := randomPrime(rand, bits/3)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
todo := bits - p.BitLen()
|
||||
q, err := randomPrime(rand, todo/2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
todo -= q.BitLen()
|
||||
r, err := randomPrime(rand, todo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if p.Cmp(q) == 0 ||
|
||||
q.Cmp(r) == 0 ||
|
||||
r.Cmp(p) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
n := new(big.Int).Mul(p, q)
|
||||
n.Mul(n, r)
|
||||
pminus1.Sub(p, bigOne)
|
||||
qminus1.Sub(q, bigOne)
|
||||
rminus1.Sub(r, bigOne)
|
||||
totient.Mul(pminus1, qminus1)
|
||||
totient.Mul(totient, rminus1)
|
||||
|
||||
g := new(big.Int)
|
||||
priv.D = new(big.Int)
|
||||
y := new(big.Int)
|
||||
e := big.NewInt(int64(priv.E))
|
||||
big.GcdInt(g, priv.D, y, e, totient)
|
||||
|
||||
if g.Cmp(bigOne) == 0 {
|
||||
priv.D.Add(priv.D, totient)
|
||||
priv.P = p
|
||||
priv.Q = q
|
||||
priv.R = r
|
||||
priv.Primes = primes
|
||||
priv.N = n
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
priv.Precompute()
|
||||
return
|
||||
}
|
||||
|
||||
@ -409,23 +372,34 @@ func modInverse(a, n *big.Int) (ia *big.Int, ok bool) {
|
||||
return x, true
|
||||
}
|
||||
|
||||
// precompute performs some calculations that speed up private key operations
|
||||
// Precompute performs some calculations that speed up private key operations
|
||||
// in the future.
|
||||
func (priv *PrivateKey) precompute() {
|
||||
priv.dP = new(big.Int).Sub(priv.P, bigOne)
|
||||
priv.dP.Mod(priv.D, priv.dP)
|
||||
func (priv *PrivateKey) Precompute() {
|
||||
if priv.Precomputed.Dp != nil {
|
||||
return
|
||||
}
|
||||
|
||||
priv.dQ = new(big.Int).Sub(priv.Q, bigOne)
|
||||
priv.dQ.Mod(priv.D, priv.dQ)
|
||||
priv.Precomputed.Dp = new(big.Int).Sub(priv.Primes[0], bigOne)
|
||||
priv.Precomputed.Dp.Mod(priv.D, priv.Precomputed.Dp)
|
||||
|
||||
priv.qInv = new(big.Int).ModInverse(priv.Q, priv.P)
|
||||
priv.Precomputed.Dq = new(big.Int).Sub(priv.Primes[1], bigOne)
|
||||
priv.Precomputed.Dq.Mod(priv.D, priv.Precomputed.Dq)
|
||||
|
||||
if priv.R != nil {
|
||||
priv.dR = new(big.Int).Sub(priv.R, bigOne)
|
||||
priv.dR.Mod(priv.D, priv.dR)
|
||||
priv.Precomputed.Qinv = new(big.Int).ModInverse(priv.Primes[1], priv.Primes[0])
|
||||
|
||||
priv.pq = new(big.Int).Mul(priv.P, priv.Q)
|
||||
priv.tr = new(big.Int).ModInverse(priv.pq, priv.R)
|
||||
r := new(big.Int).Mul(priv.Primes[0], priv.Primes[1])
|
||||
priv.Precomputed.CRTValues = make([]CRTValue, len(priv.Primes)-2)
|
||||
for i := 2; i < len(priv.Primes); i++ {
|
||||
prime := priv.Primes[i]
|
||||
values := &priv.Precomputed.CRTValues[i-2]
|
||||
|
||||
values.Exp = new(big.Int).Sub(prime, bigOne)
|
||||
values.Exp.Mod(priv.D, values.Exp)
|
||||
|
||||
values.R = new(big.Int).Set(r)
|
||||
values.Coeff = new(big.Int).ModInverse(r, prime)
|
||||
|
||||
r.Mul(r, prime)
|
||||
}
|
||||
}
|
||||
|
||||
@ -463,53 +437,41 @@ func decrypt(rand io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err os.E
|
||||
}
|
||||
bigE := big.NewInt(int64(priv.E))
|
||||
rpowe := new(big.Int).Exp(r, bigE, priv.N)
|
||||
c.Mul(c, rpowe)
|
||||
c.Mod(c, priv.N)
|
||||
cCopy := new(big.Int).Set(c)
|
||||
cCopy.Mul(cCopy, rpowe)
|
||||
cCopy.Mod(cCopy, priv.N)
|
||||
c = cCopy
|
||||
}
|
||||
|
||||
priv.rwMutex.RLock()
|
||||
|
||||
if priv.dP == nil && priv.P != nil {
|
||||
priv.rwMutex.RUnlock()
|
||||
priv.rwMutex.Lock()
|
||||
if priv.dP == nil && priv.P != nil {
|
||||
priv.precompute()
|
||||
}
|
||||
priv.rwMutex.Unlock()
|
||||
priv.rwMutex.RLock()
|
||||
}
|
||||
|
||||
if priv.dP == nil {
|
||||
if priv.Precomputed.Dp == nil {
|
||||
m = new(big.Int).Exp(c, priv.D, priv.N)
|
||||
} else {
|
||||
// We have the precalculated values needed for the CRT.
|
||||
m = new(big.Int).Exp(c, priv.dP, priv.P)
|
||||
m2 := new(big.Int).Exp(c, priv.dQ, priv.Q)
|
||||
m = new(big.Int).Exp(c, priv.Precomputed.Dp, priv.Primes[0])
|
||||
m2 := new(big.Int).Exp(c, priv.Precomputed.Dq, priv.Primes[1])
|
||||
m.Sub(m, m2)
|
||||
if m.Sign() < 0 {
|
||||
m.Add(m, priv.P)
|
||||
m.Add(m, priv.Primes[0])
|
||||
}
|
||||
m.Mul(m, priv.qInv)
|
||||
m.Mod(m, priv.P)
|
||||
m.Mul(m, priv.Q)
|
||||
m.Mul(m, priv.Precomputed.Qinv)
|
||||
m.Mod(m, priv.Primes[0])
|
||||
m.Mul(m, priv.Primes[1])
|
||||
m.Add(m, m2)
|
||||
|
||||
if priv.dR != nil {
|
||||
// 3-prime CRT.
|
||||
m2.Exp(c, priv.dR, priv.R)
|
||||
for i, values := range priv.Precomputed.CRTValues {
|
||||
prime := priv.Primes[2+i]
|
||||
m2.Exp(c, values.Exp, prime)
|
||||
m2.Sub(m2, m)
|
||||
m2.Mul(m2, priv.tr)
|
||||
m2.Mod(m2, priv.R)
|
||||
m2.Mul(m2, values.Coeff)
|
||||
m2.Mod(m2, prime)
|
||||
if m2.Sign() < 0 {
|
||||
m2.Add(m2, priv.R)
|
||||
m2.Add(m2, prime)
|
||||
}
|
||||
m2.Mul(m2, priv.pq)
|
||||
m2.Mul(m2, values.R)
|
||||
m.Add(m, m2)
|
||||
}
|
||||
}
|
||||
|
||||
priv.rwMutex.RUnlock()
|
||||
|
||||
if ir != nil {
|
||||
// Unblind.
|
||||
m.Mul(m, ir)
|
||||
|
@ -30,7 +30,20 @@ func Test3PrimeKeyGeneration(t *testing.T) {
|
||||
}
|
||||
|
||||
size := 768
|
||||
priv, err := Generate3PrimeKey(rand.Reader, size)
|
||||
priv, err := GenerateMultiPrimeKey(rand.Reader, 3, size)
|
||||
if err != nil {
|
||||
t.Errorf("failed to generate key")
|
||||
}
|
||||
testKeyBasics(t, priv)
|
||||
}
|
||||
|
||||
func Test4PrimeKeyGeneration(t *testing.T) {
|
||||
if testing.Short() {
|
||||
return
|
||||
}
|
||||
|
||||
size := 768
|
||||
priv, err := GenerateMultiPrimeKey(rand.Reader, 4, size)
|
||||
if err != nil {
|
||||
t.Errorf("failed to generate key")
|
||||
}
|
||||
@ -45,6 +58,7 @@ func testKeyBasics(t *testing.T, priv *PrivateKey) {
|
||||
pub := &priv.PublicKey
|
||||
m := big.NewInt(42)
|
||||
c := encrypt(new(big.Int), pub, m)
|
||||
|
||||
m2, err := decrypt(nil, priv, c)
|
||||
if err != nil {
|
||||
t.Errorf("error while decrypting: %s", err)
|
||||
@ -59,7 +73,7 @@ func testKeyBasics(t *testing.T, priv *PrivateKey) {
|
||||
t.Errorf("error while decrypting (blind): %s", err)
|
||||
}
|
||||
if m.Cmp(m3) != 0 {
|
||||
t.Errorf("(blind) got:%v, want:%v", m3, m)
|
||||
t.Errorf("(blind) got:%v, want:%v (%#v)", m3, m, priv)
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,10 +91,12 @@ func BenchmarkRSA2048Decrypt(b *testing.B) {
|
||||
E: 3,
|
||||
},
|
||||
D: fromBase10("9542755287494004433998723259516013739278699355114572217325597900889416163458809501304132487555642811888150937392013824621448709836142886006653296025093941418628992648429798282127303704957273845127141852309016655778568546006839666463451542076964744073572349705538631742281931858219480985907271975884773482372966847639853897890615456605598071088189838676728836833012254065983259638538107719766738032720239892094196108713378822882383694456030043492571063441943847195939549773271694647657549658603365629458610273821292232646334717612674519997533901052790334279661754176490593041941863932308687197618671528035670452762731"),
|
||||
P: fromBase10("130903255182996722426771613606077755295583329135067340152947172868415809027537376306193179624298874215608270802054347609836776473930072411958753044562214537013874103802006369634761074377213995983876788718033850153719421695468704276694983032644416930879093914927146648402139231293035971427838068945045019075433"),
|
||||
Q: fromBase10("109348945610485453577574767652527472924289229538286649661240938988020367005475727988253438647560958573506159449538793540472829815903949343191091817779240101054552748665267574271163617694640513549693841337820602726596756351006149518830932261246698766355347898158548465400674856021497190430791824869615170301029"),
|
||||
Primes: []*big.Int{
|
||||
fromBase10("130903255182996722426771613606077755295583329135067340152947172868415809027537376306193179624298874215608270802054347609836776473930072411958753044562214537013874103802006369634761074377213995983876788718033850153719421695468704276694983032644416930879093914927146648402139231293035971427838068945045019075433"),
|
||||
fromBase10("109348945610485453577574767652527472924289229538286649661240938988020367005475727988253438647560958573506159449538793540472829815903949343191091817779240101054552748665267574271163617694640513549693841337820602726596756351006149518830932261246698766355347898158548465400674856021497190430791824869615170301029"),
|
||||
},
|
||||
}
|
||||
priv.precompute()
|
||||
priv.Precompute()
|
||||
|
||||
c := fromBase10("1000")
|
||||
|
||||
@ -99,11 +115,13 @@ func Benchmark3PrimeRSA2048Decrypt(b *testing.B) {
|
||||
E: 3,
|
||||
},
|
||||
D: fromBase10("10897585948254795600358846499957366070880176878341177571733155050184921896034527397712889205732614568234385175145686545381899460748279607074689061600935843283397424506622998458510302603922766336783617368686090042765718290914099334449154829375179958369993407724946186243249568928237086215759259909861748642124071874879861299389874230489928271621259294894142840428407196932444474088857746123104978617098858619445675532587787023228852383149557470077802718705420275739737958953794088728369933811184572620857678792001136676902250566845618813972833750098806496641114644760255910789397593428910198080271317419213080834885003"),
|
||||
P: fromBase10("1025363189502892836833747188838978207017355117492483312747347695538428729137306368764177201532277413433182799108299960196606011786562992097313508180436744488171474690412562218914213688661311117337381958560443"),
|
||||
Q: fromBase10("3467903426626310123395340254094941045497208049900750380025518552334536945536837294961497712862519984786362199788654739924501424784631315081391467293694361474867825728031147665777546570788493758372218019373"),
|
||||
R: fromBase10("4597024781409332673052708605078359346966325141767460991205742124888960305710298765592730135879076084498363772408626791576005136245060321874472727132746643162385746062759369754202494417496879741537284589047"),
|
||||
Primes: []*big.Int{
|
||||
fromBase10("1025363189502892836833747188838978207017355117492483312747347695538428729137306368764177201532277413433182799108299960196606011786562992097313508180436744488171474690412562218914213688661311117337381958560443"),
|
||||
fromBase10("3467903426626310123395340254094941045497208049900750380025518552334536945536837294961497712862519984786362199788654739924501424784631315081391467293694361474867825728031147665777546570788493758372218019373"),
|
||||
fromBase10("4597024781409332673052708605078359346966325141767460991205742124888960305710298765592730135879076084498363772408626791576005136245060321874472727132746643162385746062759369754202494417496879741537284589047"),
|
||||
},
|
||||
}
|
||||
priv.precompute()
|
||||
priv.Precompute()
|
||||
|
||||
c := fromBase10("1000")
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This package implements the SHA1 hash algorithm as defined in RFC 3174.
|
||||
// Package sha1 implements the SHA1 hash algorithm as defined in RFC 3174.
|
||||
package sha1
|
||||
|
||||
import (
|
||||
|
@ -2,7 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This package implements the SHA224 and SHA256 hash algorithms as defined in FIPS 180-2.
|
||||
// Package sha256 implements the SHA224 and SHA256 hash algorithms as defined
|
||||
// in FIPS 180-2.
|
||||
package sha256
|
||||
|
||||
import (
|
||||
|
@ -2,7 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This package implements the SHA384 and SHA512 hash algorithms as defined in FIPS 180-2.
|
||||
// Package sha512 implements the SHA384 and SHA512 hash algorithms as defined
|
||||
// in FIPS 180-2.
|
||||
package sha512
|
||||
|
||||
import (
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This package implements functions that are often useful in cryptographic
|
||||
// Package subtle implements functions that are often useful in cryptographic
|
||||
// code but require careful thought to use correctly.
|
||||
package subtle
|
||||
|
||||
|
@ -1,89 +0,0 @@
|
||||
// Copyright 2009 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 tls
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// A CASet is a set of certificates.
|
||||
type CASet struct {
|
||||
bySubjectKeyId map[string][]*x509.Certificate
|
||||
byName map[string][]*x509.Certificate
|
||||
}
|
||||
|
||||
// NewCASet returns a new, empty CASet.
|
||||
func NewCASet() *CASet {
|
||||
return &CASet{
|
||||
make(map[string][]*x509.Certificate),
|
||||
make(map[string][]*x509.Certificate),
|
||||
}
|
||||
}
|
||||
|
||||
func nameToKey(name *x509.Name) string {
|
||||
return strings.Join(name.Country, ",") + "/" + strings.Join(name.Organization, ",") + "/" + strings.Join(name.OrganizationalUnit, ",") + "/" + name.CommonName
|
||||
}
|
||||
|
||||
// FindVerifiedParent attempts to find the certificate in s which has signed
|
||||
// the given certificate. If no such certificate can be found or the signature
|
||||
// doesn't match, it returns nil.
|
||||
func (s *CASet) FindVerifiedParent(cert *x509.Certificate) (parent *x509.Certificate) {
|
||||
var candidates []*x509.Certificate
|
||||
|
||||
if len(cert.AuthorityKeyId) > 0 {
|
||||
candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
|
||||
}
|
||||
if len(candidates) == 0 {
|
||||
candidates = s.byName[nameToKey(&cert.Issuer)]
|
||||
}
|
||||
|
||||
for _, c := range candidates {
|
||||
if cert.CheckSignatureFrom(c) == nil {
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddCert adds a certificate to the set
|
||||
func (s *CASet) AddCert(cert *x509.Certificate) {
|
||||
if len(cert.SubjectKeyId) > 0 {
|
||||
keyId := string(cert.SubjectKeyId)
|
||||
s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], cert)
|
||||
}
|
||||
name := nameToKey(&cert.Subject)
|
||||
s.byName[name] = append(s.byName[name], cert)
|
||||
}
|
||||
|
||||
// SetFromPEM attempts to parse a series of PEM encoded root certificates. It
|
||||
// appends any certificates found to s and returns true if any certificates
|
||||
// were successfully parsed. On many Linux systems, /etc/ssl/cert.pem will
|
||||
// contains the system wide set of root CAs in a format suitable for this
|
||||
// function.
|
||||
func (s *CASet) SetFromPEM(pemCerts []byte) (ok bool) {
|
||||
for len(pemCerts) > 0 {
|
||||
var block *pem.Block
|
||||
block, pemCerts = pem.Decode(pemCerts)
|
||||
if block == nil {
|
||||
break
|
||||
}
|
||||
if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
cert, err := x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
s.AddCert(cert)
|
||||
ok = true
|
||||
}
|
||||
|
||||
return
|
||||
}
|
@ -100,6 +100,8 @@ type ConnectionState struct {
|
||||
|
||||
// the certificate chain that was presented by the other side
|
||||
PeerCertificates []*x509.Certificate
|
||||
// the verified certificate chains built from PeerCertificates.
|
||||
VerifiedChains [][]*x509.Certificate
|
||||
}
|
||||
|
||||
// A Config structure is used to configure a TLS client or server. After one
|
||||
@ -122,7 +124,7 @@ type Config struct {
|
||||
// RootCAs defines the set of root certificate authorities
|
||||
// that clients use when verifying server certificates.
|
||||
// If RootCAs is nil, TLS uses the host's root CA set.
|
||||
RootCAs *CASet
|
||||
RootCAs *x509.CertPool
|
||||
|
||||
// NextProtos is a list of supported, application level protocols.
|
||||
NextProtos []string
|
||||
@ -158,7 +160,7 @@ func (c *Config) time() int64 {
|
||||
return t()
|
||||
}
|
||||
|
||||
func (c *Config) rootCAs() *CASet {
|
||||
func (c *Config) rootCAs() *x509.CertPool {
|
||||
s := c.RootCAs
|
||||
if s == nil {
|
||||
s = defaultRoots()
|
||||
@ -178,6 +180,9 @@ func (c *Config) cipherSuites() []uint16 {
|
||||
type Certificate struct {
|
||||
Certificate [][]byte
|
||||
PrivateKey *rsa.PrivateKey
|
||||
// OCSPStaple contains an optional OCSP response which will be served
|
||||
// to clients that request it.
|
||||
OCSPStaple []byte
|
||||
}
|
||||
|
||||
// A TLS record.
|
||||
@ -221,7 +226,7 @@ var certFiles = []string{
|
||||
|
||||
var once sync.Once
|
||||
|
||||
func defaultRoots() *CASet {
|
||||
func defaultRoots() *x509.CertPool {
|
||||
once.Do(initDefaults)
|
||||
return varDefaultRoots
|
||||
}
|
||||
@ -236,14 +241,14 @@ func initDefaults() {
|
||||
initDefaultCipherSuites()
|
||||
}
|
||||
|
||||
var varDefaultRoots *CASet
|
||||
var varDefaultRoots *x509.CertPool
|
||||
|
||||
func initDefaultRoots() {
|
||||
roots := NewCASet()
|
||||
roots := x509.NewCertPool()
|
||||
for _, file := range certFiles {
|
||||
data, err := ioutil.ReadFile(file)
|
||||
if err == nil {
|
||||
roots.SetFromPEM(data)
|
||||
roots.AppendCertsFromPEM(data)
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -255,7 +260,7 @@ var varDefaultCipherSuites []uint16
|
||||
func initDefaultCipherSuites() {
|
||||
varDefaultCipherSuites = make([]uint16, len(cipherSuites))
|
||||
i := 0
|
||||
for id, _ := range cipherSuites {
|
||||
for id := range cipherSuites {
|
||||
varDefaultCipherSuites[i] = id
|
||||
i++
|
||||
}
|
||||
|
@ -34,6 +34,9 @@ type Conn struct {
|
||||
cipherSuite uint16
|
||||
ocspResponse []byte // stapled OCSP response
|
||||
peerCertificates []*x509.Certificate
|
||||
// verifedChains contains the certificate chains that we built, as
|
||||
// opposed to the ones presented by the server.
|
||||
verifiedChains [][]*x509.Certificate
|
||||
|
||||
clientProtocol string
|
||||
clientProtocolFallback bool
|
||||
@ -765,6 +768,7 @@ func (c *Conn) ConnectionState() ConnectionState {
|
||||
state.NegotiatedProtocolIsMutual = !c.clientProtocolFallback
|
||||
state.CipherSuite = c.cipherSuite
|
||||
state.PeerCertificates = c.peerCertificates
|
||||
state.VerifiedChains = c.verifiedChains
|
||||
}
|
||||
|
||||
return state
|
||||
|
@ -88,7 +88,6 @@ func (c *Conn) clientHandshake() os.Error {
|
||||
finishedHash.Write(certMsg.marshal())
|
||||
|
||||
certs := make([]*x509.Certificate, len(certMsg.certificates))
|
||||
chain := NewCASet()
|
||||
for i, asn1Data := range certMsg.certificates {
|
||||
cert, err := x509.ParseCertificate(asn1Data)
|
||||
if err != nil {
|
||||
@ -96,47 +95,29 @@ func (c *Conn) clientHandshake() os.Error {
|
||||
return os.ErrorString("failed to parse certificate from server: " + err.String())
|
||||
}
|
||||
certs[i] = cert
|
||||
chain.AddCert(cert)
|
||||
}
|
||||
|
||||
// If we don't have a root CA set configured then anything is accepted.
|
||||
// TODO(rsc): Find certificates for OS X 10.6.
|
||||
for cur := certs[0]; c.config.RootCAs != nil; {
|
||||
parent := c.config.RootCAs.FindVerifiedParent(cur)
|
||||
if parent != nil {
|
||||
break
|
||||
if c.config.RootCAs != nil {
|
||||
opts := x509.VerifyOptions{
|
||||
Roots: c.config.RootCAs,
|
||||
CurrentTime: c.config.time(),
|
||||
DNSName: c.config.ServerName,
|
||||
Intermediates: x509.NewCertPool(),
|
||||
}
|
||||
|
||||
parent = chain.FindVerifiedParent(cur)
|
||||
if parent == nil {
|
||||
for i, cert := range certs {
|
||||
if i == 0 {
|
||||
continue
|
||||
}
|
||||
opts.Intermediates.AddCert(cert)
|
||||
}
|
||||
c.verifiedChains, err = certs[0].Verify(opts)
|
||||
if err != nil {
|
||||
c.sendAlert(alertBadCertificate)
|
||||
return os.ErrorString("could not find root certificate for chain")
|
||||
return err
|
||||
}
|
||||
|
||||
if !parent.BasicConstraintsValid || !parent.IsCA {
|
||||
c.sendAlert(alertBadCertificate)
|
||||
return os.ErrorString("intermediate certificate does not have CA bit set")
|
||||
}
|
||||
// KeyUsage status flags are ignored. From Engineering
|
||||
// Security, Peter Gutmann: A European government CA marked its
|
||||
// signing certificates as being valid for encryption only, but
|
||||
// no-one noticed. Another European CA marked its signature
|
||||
// keys as not being valid for signatures. A different CA
|
||||
// marked its own trusted root certificate as being invalid for
|
||||
// certificate signing. Another national CA distributed a
|
||||
// certificate to be used to encrypt data for the country’s tax
|
||||
// authority that was marked as only being usable for digital
|
||||
// signatures but not for encryption. Yet another CA reversed
|
||||
// the order of the bit flags in the keyUsage due to confusion
|
||||
// over encoding endianness, essentially setting a random
|
||||
// keyUsage in certificates that it issued. Another CA created
|
||||
// a self-invalidating certificate by adding a certificate
|
||||
// policy statement stipulating that the certificate had to be
|
||||
// used strictly as specified in the keyUsage, and a keyUsage
|
||||
// containing a flag indicating that the RSA encryption key
|
||||
// could only be used for Diffie-Hellman key agreement.
|
||||
|
||||
cur = parent
|
||||
}
|
||||
|
||||
if _, ok := certs[0].PublicKey.(*rsa.PublicKey); !ok {
|
||||
@ -145,7 +126,7 @@ func (c *Conn) clientHandshake() os.Error {
|
||||
|
||||
c.peerCertificates = certs
|
||||
|
||||
if serverHello.certStatus {
|
||||
if serverHello.ocspStapling {
|
||||
msg, err = c.readHandshake()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -306,7 +306,7 @@ type serverHelloMsg struct {
|
||||
compressionMethod uint8
|
||||
nextProtoNeg bool
|
||||
nextProtos []string
|
||||
certStatus bool
|
||||
ocspStapling bool
|
||||
}
|
||||
|
||||
func (m *serverHelloMsg) marshal() []byte {
|
||||
@ -327,7 +327,7 @@ func (m *serverHelloMsg) marshal() []byte {
|
||||
nextProtoLen += len(m.nextProtos)
|
||||
extensionsLength += nextProtoLen
|
||||
}
|
||||
if m.certStatus {
|
||||
if m.ocspStapling {
|
||||
numExtensions++
|
||||
}
|
||||
if numExtensions > 0 {
|
||||
@ -373,7 +373,7 @@ func (m *serverHelloMsg) marshal() []byte {
|
||||
z = z[1+l:]
|
||||
}
|
||||
}
|
||||
if m.certStatus {
|
||||
if m.ocspStapling {
|
||||
z[0] = byte(extensionStatusRequest >> 8)
|
||||
z[1] = byte(extensionStatusRequest)
|
||||
z = z[4:]
|
||||
@ -406,7 +406,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
|
||||
|
||||
m.nextProtoNeg = false
|
||||
m.nextProtos = nil
|
||||
m.certStatus = false
|
||||
m.ocspStapling = false
|
||||
|
||||
if len(data) == 0 {
|
||||
// ServerHello is optionally followed by extension data
|
||||
@ -450,7 +450,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
|
||||
if length > 0 {
|
||||
return false
|
||||
}
|
||||
m.certStatus = true
|
||||
m.ocspStapling = true
|
||||
}
|
||||
data = data[length:]
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ type testMessage interface {
|
||||
func TestMarshalUnmarshal(t *testing.T) {
|
||||
rand := rand.New(rand.NewSource(0))
|
||||
for i, iface := range tests {
|
||||
ty := reflect.NewValue(iface).Type()
|
||||
ty := reflect.ValueOf(iface).Type()
|
||||
|
||||
n := 100
|
||||
if testing.Short() {
|
||||
@ -121,11 +121,11 @@ func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
|
||||
m.ocspStapling = rand.Intn(10) > 5
|
||||
m.supportedPoints = randomBytes(rand.Intn(5)+1, rand)
|
||||
m.supportedCurves = make([]uint16, rand.Intn(5)+1)
|
||||
for i, _ := range m.supportedCurves {
|
||||
for i := range m.supportedCurves {
|
||||
m.supportedCurves[i] = uint16(rand.Intn(30000))
|
||||
}
|
||||
|
||||
return reflect.NewValue(m)
|
||||
return reflect.ValueOf(m)
|
||||
}
|
||||
|
||||
func (*serverHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
|
||||
@ -146,7 +146,7 @@ func (*serverHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
|
||||
}
|
||||
}
|
||||
|
||||
return reflect.NewValue(m)
|
||||
return reflect.ValueOf(m)
|
||||
}
|
||||
|
||||
func (*certificateMsg) Generate(rand *rand.Rand, size int) reflect.Value {
|
||||
@ -156,7 +156,7 @@ func (*certificateMsg) Generate(rand *rand.Rand, size int) reflect.Value {
|
||||
for i := 0; i < numCerts; i++ {
|
||||
m.certificates[i] = randomBytes(rand.Intn(10)+1, rand)
|
||||
}
|
||||
return reflect.NewValue(m)
|
||||
return reflect.ValueOf(m)
|
||||
}
|
||||
|
||||
func (*certificateRequestMsg) Generate(rand *rand.Rand, size int) reflect.Value {
|
||||
@ -167,13 +167,13 @@ func (*certificateRequestMsg) Generate(rand *rand.Rand, size int) reflect.Value
|
||||
for i := 0; i < numCAs; i++ {
|
||||
m.certificateAuthorities[i] = randomBytes(rand.Intn(15)+1, rand)
|
||||
}
|
||||
return reflect.NewValue(m)
|
||||
return reflect.ValueOf(m)
|
||||
}
|
||||
|
||||
func (*certificateVerifyMsg) Generate(rand *rand.Rand, size int) reflect.Value {
|
||||
m := &certificateVerifyMsg{}
|
||||
m.signature = randomBytes(rand.Intn(15)+1, rand)
|
||||
return reflect.NewValue(m)
|
||||
return reflect.ValueOf(m)
|
||||
}
|
||||
|
||||
func (*certificateStatusMsg) Generate(rand *rand.Rand, size int) reflect.Value {
|
||||
@ -184,23 +184,23 @@ func (*certificateStatusMsg) Generate(rand *rand.Rand, size int) reflect.Value {
|
||||
} else {
|
||||
m.statusType = 42
|
||||
}
|
||||
return reflect.NewValue(m)
|
||||
return reflect.ValueOf(m)
|
||||
}
|
||||
|
||||
func (*clientKeyExchangeMsg) Generate(rand *rand.Rand, size int) reflect.Value {
|
||||
m := &clientKeyExchangeMsg{}
|
||||
m.ciphertext = randomBytes(rand.Intn(1000)+1, rand)
|
||||
return reflect.NewValue(m)
|
||||
return reflect.ValueOf(m)
|
||||
}
|
||||
|
||||
func (*finishedMsg) Generate(rand *rand.Rand, size int) reflect.Value {
|
||||
m := &finishedMsg{}
|
||||
m.verifyData = randomBytes(12, rand)
|
||||
return reflect.NewValue(m)
|
||||
return reflect.ValueOf(m)
|
||||
}
|
||||
|
||||
func (*nextProtoMsg) Generate(rand *rand.Rand, size int) reflect.Value {
|
||||
m := &nextProtoMsg{}
|
||||
m.proto = randomString(rand.Intn(255), rand)
|
||||
return reflect.NewValue(m)
|
||||
return reflect.ValueOf(m)
|
||||
}
|
||||
|
@ -103,6 +103,9 @@ FindCipherSuite:
|
||||
hello.nextProtoNeg = true
|
||||
hello.nextProtos = config.NextProtos
|
||||
}
|
||||
if clientHello.ocspStapling && len(config.Certificates[0].OCSPStaple) > 0 {
|
||||
hello.ocspStapling = true
|
||||
}
|
||||
|
||||
finishedHash.Write(hello.marshal())
|
||||
c.writeRecord(recordTypeHandshake, hello.marshal())
|
||||
@ -116,6 +119,14 @@ FindCipherSuite:
|
||||
finishedHash.Write(certMsg.marshal())
|
||||
c.writeRecord(recordTypeHandshake, certMsg.marshal())
|
||||
|
||||
if hello.ocspStapling {
|
||||
certStatus := new(certificateStatusMsg)
|
||||
certStatus.statusType = statusTypeOCSP
|
||||
certStatus.response = config.Certificates[0].OCSPStaple
|
||||
finishedHash.Write(certStatus.marshal())
|
||||
c.writeRecord(recordTypeHandshake, certStatus.marshal())
|
||||
}
|
||||
|
||||
keyAgreement := suite.ka()
|
||||
|
||||
skx, err := keyAgreement.generateServerKeyExchange(config, clientHello, hello)
|
||||
|
@ -188,8 +188,10 @@ var testPrivateKey = &rsa.PrivateKey{
|
||||
E: 65537,
|
||||
},
|
||||
D: bigFromString("29354450337804273969007277378287027274721892607543397931919078829901848876371746653677097639302788129485893852488285045793268732234230875671682624082413996177431586734171663258657462237320300610850244186316880055243099640544518318093544057213190320837094958164973959123058337475052510833916491060913053867729"),
|
||||
P: bigFromString("11969277782311800166562047708379380720136961987713178380670422671426759650127150688426177829077494755200794297055316163155755835813760102405344560929062149"),
|
||||
Q: bigFromString("10998999429884441391899182616418192492905073053684657075974935218461686523870125521822756579792315215543092255516093840728890783887287417039645833477273829"),
|
||||
Primes: []*big.Int{
|
||||
bigFromString("11969277782311800166562047708379380720136961987713178380670422671426759650127150688426177829077494755200794297055316163155755835813760102405344560929062149"),
|
||||
bigFromString("10998999429884441391899182616418192492905073053684657075974935218461686523870125521822756579792315215543092255516093840728890783887287417039645833477273829"),
|
||||
},
|
||||
}
|
||||
|
||||
// Script of interaction with gnutls implementation.
|
||||
|
@ -2,7 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This package partially implements the TLS 1.1 protocol, as specified in RFC 4346.
|
||||
// Package tls partially implements the TLS 1.1 protocol, as specified in RFC
|
||||
// 4346.
|
||||
package tls
|
||||
|
||||
import (
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This package implements Bruce Schneier's Twofish encryption algorithm.
|
||||
// Package twofish implements Bruce Schneier's Twofish encryption algorithm.
|
||||
package twofish
|
||||
|
||||
// Twofish is defined in http://www.schneier.com/paper-twofish-paper.pdf [TWOFISH]
|
||||
|
105
libgo/go/crypto/x509/cert_pool.go
Normal file
105
libgo/go/crypto/x509/cert_pool.go
Normal file
@ -0,0 +1,105 @@
|
||||
// Copyright 2011 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 x509
|
||||
|
||||
import (
|
||||
"encoding/pem"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Roots is a set of certificates.
|
||||
type CertPool struct {
|
||||
bySubjectKeyId map[string][]int
|
||||
byName map[string][]int
|
||||
certs []*Certificate
|
||||
}
|
||||
|
||||
// NewCertPool returns a new, empty CertPool.
|
||||
func NewCertPool() *CertPool {
|
||||
return &CertPool{
|
||||
make(map[string][]int),
|
||||
make(map[string][]int),
|
||||
nil,
|
||||
}
|
||||
}
|
||||
|
||||
func nameToKey(name *Name) string {
|
||||
return strings.Join(name.Country, ",") + "/" + strings.Join(name.Organization, ",") + "/" + strings.Join(name.OrganizationalUnit, ",") + "/" + name.CommonName
|
||||
}
|
||||
|
||||
// findVerifiedParents attempts to find certificates in s which have signed the
|
||||
// given certificate. If no such certificate can be found or the signature
|
||||
// doesn't match, it returns nil.
|
||||
func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int) {
|
||||
var candidates []int
|
||||
|
||||
if len(cert.AuthorityKeyId) > 0 {
|
||||
candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
|
||||
}
|
||||
if len(candidates) == 0 {
|
||||
candidates = s.byName[nameToKey(&cert.Issuer)]
|
||||
}
|
||||
|
||||
for _, c := range candidates {
|
||||
if cert.CheckSignatureFrom(s.certs[c]) == nil {
|
||||
parents = append(parents, c)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// AddCert adds a certificate to a pool.
|
||||
func (s *CertPool) AddCert(cert *Certificate) {
|
||||
if cert == nil {
|
||||
panic("adding nil Certificate to CertPool")
|
||||
}
|
||||
|
||||
// Check that the certificate isn't being added twice.
|
||||
for _, c := range s.certs {
|
||||
if c.Equal(cert) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
n := len(s.certs)
|
||||
s.certs = append(s.certs, cert)
|
||||
|
||||
if len(cert.SubjectKeyId) > 0 {
|
||||
keyId := string(cert.SubjectKeyId)
|
||||
s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n)
|
||||
}
|
||||
name := nameToKey(&cert.Subject)
|
||||
s.byName[name] = append(s.byName[name], n)
|
||||
}
|
||||
|
||||
// AppendCertsFromPEM attempts to parse a series of PEM encoded root
|
||||
// certificates. It appends any certificates found to s and returns true if any
|
||||
// certificates were successfully parsed.
|
||||
//
|
||||
// On many Linux systems, /etc/ssl/cert.pem will contains the system wide set
|
||||
// of root CAs in a format suitable for this function.
|
||||
func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) {
|
||||
for len(pemCerts) > 0 {
|
||||
var block *pem.Block
|
||||
block, pemCerts = pem.Decode(pemCerts)
|
||||
if block == nil {
|
||||
break
|
||||
}
|
||||
if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
cert, err := ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
s.AddCert(cert)
|
||||
ok = true
|
||||
}
|
||||
|
||||
return
|
||||
}
|
239
libgo/go/crypto/x509/verify.go
Normal file
239
libgo/go/crypto/x509/verify.go
Normal file
@ -0,0 +1,239 @@
|
||||
// Copyright 2011 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 x509
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type InvalidReason int
|
||||
|
||||
const (
|
||||
// NotAuthorizedToSign results when a certificate is signed by another
|
||||
// which isn't marked as a CA certificate.
|
||||
NotAuthorizedToSign InvalidReason = iota
|
||||
// Expired results when a certificate has expired, based on the time
|
||||
// given in the VerifyOptions.
|
||||
Expired
|
||||
// CANotAuthorizedForThisName results when an intermediate or root
|
||||
// certificate has a name constraint which doesn't include the name
|
||||
// being checked.
|
||||
CANotAuthorizedForThisName
|
||||
)
|
||||
|
||||
// CertificateInvalidError results when an odd error occurs. Users of this
|
||||
// library probably want to handle all these errors uniformly.
|
||||
type CertificateInvalidError struct {
|
||||
Cert *Certificate
|
||||
Reason InvalidReason
|
||||
}
|
||||
|
||||
func (e CertificateInvalidError) String() string {
|
||||
switch e.Reason {
|
||||
case NotAuthorizedToSign:
|
||||
return "x509: certificate is not authorized to sign other other certificates"
|
||||
case Expired:
|
||||
return "x509: certificate has expired or is not yet valid"
|
||||
case CANotAuthorizedForThisName:
|
||||
return "x509: a root or intermediate certificate is not authorized to sign in this domain"
|
||||
}
|
||||
return "x509: unknown error"
|
||||
}
|
||||
|
||||
// HostnameError results when the set of authorized names doesn't match the
|
||||
// requested name.
|
||||
type HostnameError struct {
|
||||
Certificate *Certificate
|
||||
Host string
|
||||
}
|
||||
|
||||
func (h HostnameError) String() string {
|
||||
var valid string
|
||||
c := h.Certificate
|
||||
if len(c.DNSNames) > 0 {
|
||||
valid = strings.Join(c.DNSNames, ", ")
|
||||
} else {
|
||||
valid = c.Subject.CommonName
|
||||
}
|
||||
return "certificate is valid for " + valid + ", not " + h.Host
|
||||
}
|
||||
|
||||
|
||||
// UnknownAuthorityError results when the certificate issuer is unknown
|
||||
type UnknownAuthorityError struct {
|
||||
cert *Certificate
|
||||
}
|
||||
|
||||
func (e UnknownAuthorityError) String() string {
|
||||
return "x509: certificate signed by unknown authority"
|
||||
}
|
||||
|
||||
// VerifyOptions contains parameters for Certificate.Verify. It's a structure
|
||||
// because other PKIX verification APIs have ended up needing many options.
|
||||
type VerifyOptions struct {
|
||||
DNSName string
|
||||
Intermediates *CertPool
|
||||
Roots *CertPool
|
||||
CurrentTime int64 // if 0, the current system time is used.
|
||||
}
|
||||
|
||||
const (
|
||||
leafCertificate = iota
|
||||
intermediateCertificate
|
||||
rootCertificate
|
||||
)
|
||||
|
||||
// isValid performs validity checks on the c.
|
||||
func (c *Certificate) isValid(certType int, opts *VerifyOptions) os.Error {
|
||||
if opts.CurrentTime < c.NotBefore.Seconds() ||
|
||||
opts.CurrentTime > c.NotAfter.Seconds() {
|
||||
return CertificateInvalidError{c, Expired}
|
||||
}
|
||||
|
||||
if len(c.PermittedDNSDomains) > 0 {
|
||||
for _, domain := range c.PermittedDNSDomains {
|
||||
if opts.DNSName == domain ||
|
||||
(strings.HasSuffix(opts.DNSName, domain) &&
|
||||
len(opts.DNSName) >= 1+len(domain) &&
|
||||
opts.DNSName[len(opts.DNSName)-len(domain)-1] == '.') {
|
||||
continue
|
||||
}
|
||||
|
||||
return CertificateInvalidError{c, CANotAuthorizedForThisName}
|
||||
}
|
||||
}
|
||||
|
||||
// KeyUsage status flags are ignored. From Engineering Security, Peter
|
||||
// Gutmann: A European government CA marked its signing certificates as
|
||||
// being valid for encryption only, but no-one noticed. Another
|
||||
// European CA marked its signature keys as not being valid for
|
||||
// signatures. A different CA marked its own trusted root certificate
|
||||
// as being invalid for certificate signing. Another national CA
|
||||
// distributed a certificate to be used to encrypt data for the
|
||||
// country’s tax authority that was marked as only being usable for
|
||||
// digital signatures but not for encryption. Yet another CA reversed
|
||||
// the order of the bit flags in the keyUsage due to confusion over
|
||||
// encoding endianness, essentially setting a random keyUsage in
|
||||
// certificates that it issued. Another CA created a self-invalidating
|
||||
// certificate by adding a certificate policy statement stipulating
|
||||
// that the certificate had to be used strictly as specified in the
|
||||
// keyUsage, and a keyUsage containing a flag indicating that the RSA
|
||||
// encryption key could only be used for Diffie-Hellman key agreement.
|
||||
|
||||
if certType == intermediateCertificate && (!c.BasicConstraintsValid || !c.IsCA) {
|
||||
return CertificateInvalidError{c, NotAuthorizedToSign}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Verify attempts to verify c by building one or more chains from c to a
|
||||
// certificate in opts.roots, using certificates in opts.Intermediates if
|
||||
// needed. If successful, it returns one or chains where the first element of
|
||||
// the chain is c and the last element is from opts.Roots.
|
||||
//
|
||||
// WARNING: this doesn't do any revocation checking.
|
||||
func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err os.Error) {
|
||||
if opts.CurrentTime == 0 {
|
||||
opts.CurrentTime = time.Seconds()
|
||||
}
|
||||
err = c.isValid(leafCertificate, &opts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(opts.DNSName) > 0 {
|
||||
err = c.VerifyHostname(opts.DNSName)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return c.buildChains(make(map[int][][]*Certificate), []*Certificate{c}, &opts)
|
||||
}
|
||||
|
||||
func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate {
|
||||
n := make([]*Certificate, len(chain)+1)
|
||||
copy(n, chain)
|
||||
n[len(chain)] = cert
|
||||
return n
|
||||
}
|
||||
|
||||
func (c *Certificate) buildChains(cache map[int][][]*Certificate, currentChain []*Certificate, opts *VerifyOptions) (chains [][]*Certificate, err os.Error) {
|
||||
for _, rootNum := range opts.Roots.findVerifiedParents(c) {
|
||||
root := opts.Roots.certs[rootNum]
|
||||
err = root.isValid(rootCertificate, opts)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
chains = append(chains, appendToFreshChain(currentChain, root))
|
||||
}
|
||||
|
||||
for _, intermediateNum := range opts.Intermediates.findVerifiedParents(c) {
|
||||
intermediate := opts.Intermediates.certs[intermediateNum]
|
||||
err = intermediate.isValid(intermediateCertificate, opts)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
var childChains [][]*Certificate
|
||||
childChains, ok := cache[intermediateNum]
|
||||
if !ok {
|
||||
childChains, err = intermediate.buildChains(cache, appendToFreshChain(currentChain, intermediate), opts)
|
||||
cache[intermediateNum] = childChains
|
||||
}
|
||||
chains = append(chains, childChains...)
|
||||
}
|
||||
|
||||
if len(chains) > 0 {
|
||||
err = nil
|
||||
}
|
||||
|
||||
if len(chains) == 0 && err == nil {
|
||||
err = UnknownAuthorityError{c}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func matchHostnames(pattern, host string) bool {
|
||||
if len(pattern) == 0 || len(host) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
patternParts := strings.Split(pattern, ".", -1)
|
||||
hostParts := strings.Split(host, ".", -1)
|
||||
|
||||
if len(patternParts) != len(hostParts) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i, patternPart := range patternParts {
|
||||
if patternPart == "*" {
|
||||
continue
|
||||
}
|
||||
if patternPart != hostParts[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// VerifyHostname returns nil if c is a valid certificate for the named host.
|
||||
// Otherwise it returns an os.Error describing the mismatch.
|
||||
func (c *Certificate) VerifyHostname(h string) os.Error {
|
||||
if len(c.DNSNames) > 0 {
|
||||
for _, match := range c.DNSNames {
|
||||
if matchHostnames(match, h) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
// If Subject Alt Name is given, we ignore the common name.
|
||||
} else if matchHostnames(c.Subject.CommonName, h) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return HostnameError{c, h}
|
||||
}
|
390
libgo/go/crypto/x509/verify_test.go
Normal file
390
libgo/go/crypto/x509/verify_test.go
Normal file
@ -0,0 +1,390 @@
|
||||
// Copyright 2011 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 x509
|
||||
|
||||
import (
|
||||
"encoding/pem"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type verifyTest struct {
|
||||
leaf string
|
||||
intermediates []string
|
||||
roots []string
|
||||
currentTime int64
|
||||
dnsName string
|
||||
|
||||
errorCallback func(*testing.T, int, os.Error) bool
|
||||
expectedChains [][]string
|
||||
}
|
||||
|
||||
var verifyTests = []verifyTest{
|
||||
{
|
||||
leaf: googleLeaf,
|
||||
intermediates: []string{thawteIntermediate},
|
||||
roots: []string{verisignRoot},
|
||||
currentTime: 1302726541,
|
||||
dnsName: "www.google.com",
|
||||
|
||||
expectedChains: [][]string{
|
||||
[]string{"Google", "Thawte", "VeriSign"},
|
||||
},
|
||||
},
|
||||
{
|
||||
leaf: googleLeaf,
|
||||
intermediates: []string{thawteIntermediate},
|
||||
roots: []string{verisignRoot},
|
||||
currentTime: 1302726541,
|
||||
dnsName: "www.example.com",
|
||||
|
||||
errorCallback: expectHostnameError,
|
||||
},
|
||||
{
|
||||
leaf: googleLeaf,
|
||||
intermediates: []string{thawteIntermediate},
|
||||
roots: []string{verisignRoot},
|
||||
currentTime: 1,
|
||||
dnsName: "www.example.com",
|
||||
|
||||
errorCallback: expectExpired,
|
||||
},
|
||||
{
|
||||
leaf: googleLeaf,
|
||||
roots: []string{verisignRoot},
|
||||
currentTime: 1302726541,
|
||||
dnsName: "www.google.com",
|
||||
|
||||
errorCallback: expectAuthorityUnknown,
|
||||
},
|
||||
{
|
||||
leaf: googleLeaf,
|
||||
intermediates: []string{verisignRoot, thawteIntermediate},
|
||||
roots: []string{verisignRoot},
|
||||
currentTime: 1302726541,
|
||||
dnsName: "www.google.com",
|
||||
|
||||
expectedChains: [][]string{
|
||||
[]string{"Google", "Thawte", "VeriSign"},
|
||||
},
|
||||
},
|
||||
{
|
||||
leaf: googleLeaf,
|
||||
intermediates: []string{verisignRoot, thawteIntermediate},
|
||||
roots: []string{verisignRoot},
|
||||
currentTime: 1302726541,
|
||||
|
||||
expectedChains: [][]string{
|
||||
[]string{"Google", "Thawte", "VeriSign"},
|
||||
},
|
||||
},
|
||||
{
|
||||
leaf: dnssecExpLeaf,
|
||||
intermediates: []string{startComIntermediate},
|
||||
roots: []string{startComRoot},
|
||||
currentTime: 1302726541,
|
||||
|
||||
expectedChains: [][]string{
|
||||
[]string{"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func expectHostnameError(t *testing.T, i int, err os.Error) (ok bool) {
|
||||
if _, ok := err.(HostnameError); !ok {
|
||||
t.Errorf("#%d: error was not a HostnameError: %s", i, err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func expectExpired(t *testing.T, i int, err os.Error) (ok bool) {
|
||||
if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != Expired {
|
||||
t.Errorf("#%d: error was not Expired: %s", i, err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func expectAuthorityUnknown(t *testing.T, i int, err os.Error) (ok bool) {
|
||||
if _, ok := err.(UnknownAuthorityError); !ok {
|
||||
t.Errorf("#%d: error was not UnknownAuthorityError: %s", i, err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func certificateFromPEM(pemBytes string) (*Certificate, os.Error) {
|
||||
block, _ := pem.Decode([]byte(pemBytes))
|
||||
if block == nil {
|
||||
return nil, os.ErrorString("failed to decode PEM")
|
||||
}
|
||||
return ParseCertificate(block.Bytes)
|
||||
}
|
||||
|
||||
func TestVerify(t *testing.T) {
|
||||
for i, test := range verifyTests {
|
||||
opts := VerifyOptions{
|
||||
Roots: NewCertPool(),
|
||||
Intermediates: NewCertPool(),
|
||||
DNSName: test.dnsName,
|
||||
CurrentTime: test.currentTime,
|
||||
}
|
||||
|
||||
for j, root := range test.roots {
|
||||
ok := opts.Roots.AppendCertsFromPEM([]byte(root))
|
||||
if !ok {
|
||||
t.Errorf("#%d: failed to parse root #%d", i, j)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
for j, intermediate := range test.intermediates {
|
||||
ok := opts.Intermediates.AppendCertsFromPEM([]byte(intermediate))
|
||||
if !ok {
|
||||
t.Errorf("#%d: failed to parse intermediate #%d", i, j)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
leaf, err := certificateFromPEM(test.leaf)
|
||||
if err != nil {
|
||||
t.Errorf("#%d: failed to parse leaf: %s", i, err)
|
||||
return
|
||||
}
|
||||
|
||||
chains, err := leaf.Verify(opts)
|
||||
|
||||
if test.errorCallback == nil && err != nil {
|
||||
t.Errorf("#%d: unexpected error: %s", i, err)
|
||||
}
|
||||
if test.errorCallback != nil {
|
||||
if !test.errorCallback(t, i, err) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if len(chains) != len(test.expectedChains) {
|
||||
t.Errorf("#%d: wanted %d chains, got %d", i, len(test.expectedChains), len(chains))
|
||||
}
|
||||
|
||||
// We check that each returned chain matches a chain from
|
||||
// expectedChains but an entry in expectedChains can't match
|
||||
// two chains.
|
||||
seenChains := make([]bool, len(chains))
|
||||
NextOutputChain:
|
||||
for _, chain := range chains {
|
||||
TryNextExpected:
|
||||
for j, expectedChain := range test.expectedChains {
|
||||
if seenChains[j] {
|
||||
continue
|
||||
}
|
||||
if len(chain) != len(expectedChain) {
|
||||
continue
|
||||
}
|
||||
for k, cert := range chain {
|
||||
if strings.Index(nameToKey(&cert.Subject), expectedChain[k]) == -1 {
|
||||
continue TryNextExpected
|
||||
}
|
||||
}
|
||||
// we matched
|
||||
seenChains[j] = true
|
||||
continue NextOutputChain
|
||||
}
|
||||
t.Errorf("#%d: No expected chain matched %s", i, chainToDebugString(chain))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func chainToDebugString(chain []*Certificate) string {
|
||||
var chainStr string
|
||||
for _, cert := range chain {
|
||||
if len(chainStr) > 0 {
|
||||
chainStr += " -> "
|
||||
}
|
||||
chainStr += nameToKey(&cert.Subject)
|
||||
}
|
||||
return chainStr
|
||||
}
|
||||
|
||||
const verisignRoot = `-----BEGIN CERTIFICATE-----
|
||||
MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG
|
||||
A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
|
||||
cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
|
||||
MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
|
||||
BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt
|
||||
YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
|
||||
ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE
|
||||
BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is
|
||||
I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G
|
||||
CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do
|
||||
lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc
|
||||
AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k
|
||||
-----END CERTIFICATE-----
|
||||
`
|
||||
|
||||
const thawteIntermediate = `-----BEGIN CERTIFICATE-----
|
||||
MIIDIzCCAoygAwIBAgIEMAAAAjANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJV
|
||||
UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDMgUHVi
|
||||
bGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNTEzMDAw
|
||||
MDAwWhcNMTQwNTEyMjM1OTU5WjBMMQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhh
|
||||
d3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBD
|
||||
QTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1NNn0I0Vf67NMf59HZGhPwtx
|
||||
PKzMyGT7Y/wySweUvW+Aui/hBJPAM/wJMyPpC3QrccQDxtLN4i/1CWPN/0ilAL/g
|
||||
5/OIty0y3pg25gqtAHvEZEo7hHUD8nCSfQ5i9SGraTaEMXWQ+L/HbIgbBpV8yeWo
|
||||
3nWhLHpo39XKHIdYYBkCAwEAAaOB/jCB+zASBgNVHRMBAf8ECDAGAQH/AgEAMAsG
|
||||
A1UdDwQEAwIBBjARBglghkgBhvhCAQEEBAMCAQYwKAYDVR0RBCEwH6QdMBsxGTAX
|
||||
BgNVBAMTEFByaXZhdGVMYWJlbDMtMTUwMQYDVR0fBCowKDAmoCSgIoYgaHR0cDov
|
||||
L2NybC52ZXJpc2lnbi5jb20vcGNhMy5jcmwwMgYIKwYBBQUHAQEEJjAkMCIGCCsG
|
||||
AQUFBzABhhZodHRwOi8vb2NzcC50aGF3dGUuY29tMDQGA1UdJQQtMCsGCCsGAQUF
|
||||
BwMBBggrBgEFBQcDAgYJYIZIAYb4QgQBBgpghkgBhvhFAQgBMA0GCSqGSIb3DQEB
|
||||
BQUAA4GBAFWsY+reod3SkF+fC852vhNRj5PZBSvIG3dLrWlQoe7e3P3bB+noOZTc
|
||||
q3J5Lwa/q4FwxKjt6lM07e8eU9kGx1Yr0Vz00YqOtCuxN5BICEIlxT6Ky3/rbwTR
|
||||
bcV0oveifHtgPHfNDs5IAn8BL7abN+AqKjbc1YXWrOU/VG+WHgWv
|
||||
-----END CERTIFICATE-----
|
||||
`
|
||||
|
||||
const googleLeaf = `-----BEGIN CERTIFICATE-----
|
||||
MIIDITCCAoqgAwIBAgIQL9+89q6RUm0PmqPfQDQ+mjANBgkqhkiG9w0BAQUFADBM
|
||||
MQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkg
|
||||
THRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBDQTAeFw0wOTEyMTgwMDAwMDBaFw0x
|
||||
MTEyMTgyMzU5NTlaMGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlh
|
||||
MRYwFAYDVQQHFA1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKFApHb29nbGUgSW5jMRcw
|
||||
FQYDVQQDFA53d3cuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
|
||||
gYEA6PmGD5D6htffvXImttdEAoN4c9kCKO+IRTn7EOh8rqk41XXGOOsKFQebg+jN
|
||||
gtXj9xVoRaELGYW84u+E593y17iYwqG7tcFR39SDAqc9BkJb4SLD3muFXxzW2k6L
|
||||
05vuuWciKh0R73mkszeK9P4Y/bz5RiNQl/Os/CRGK1w7t0UCAwEAAaOB5zCB5DAM
|
||||
BgNVHRMBAf8EAjAAMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwudGhhd3Rl
|
||||
LmNvbS9UaGF3dGVTR0NDQS5jcmwwKAYDVR0lBCEwHwYIKwYBBQUHAwEGCCsGAQUF
|
||||
BwMCBglghkgBhvhCBAEwcgYIKwYBBQUHAQEEZjBkMCIGCCsGAQUFBzABhhZodHRw
|
||||
Oi8vb2NzcC50aGF3dGUuY29tMD4GCCsGAQUFBzAChjJodHRwOi8vd3d3LnRoYXd0
|
||||
ZS5jb20vcmVwb3NpdG9yeS9UaGF3dGVfU0dDX0NBLmNydDANBgkqhkiG9w0BAQUF
|
||||
AAOBgQCfQ89bxFApsb/isJr/aiEdLRLDLE5a+RLizrmCUi3nHX4adpaQedEkUjh5
|
||||
u2ONgJd8IyAPkU0Wueru9G2Jysa9zCRo1kNbzipYvzwY4OA8Ys+WAi0oR1A04Se6
|
||||
z5nRUP8pJcA2NhUzUnC+MY+f6H/nEQyNv4SgQhqAibAxWEEHXw==
|
||||
-----END CERTIFICATE-----`
|
||||
|
||||
const dnssecExpLeaf = `-----BEGIN CERTIFICATE-----
|
||||
MIIGzTCCBbWgAwIBAgIDAdD6MA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ
|
||||
TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0
|
||||
YWwgQ2VydGlmaWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3Mg
|
||||
MSBQcmltYXJ5IEludGVybWVkaWF0ZSBTZXJ2ZXIgQ0EwHhcNMTAwNzA0MTQ1MjQ1
|
||||
WhcNMTEwNzA1MTA1NzA0WjCBwTEgMB4GA1UEDRMXMjIxMTM3LWxpOWE5dHhJRzZM
|
||||
NnNyVFMxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVQZXJzb25hIE5vdCBWYWxpZGF0
|
||||
ZWQxKTAnBgNVBAsTIFN0YXJ0Q29tIEZyZWUgQ2VydGlmaWNhdGUgTWVtYmVyMRsw
|
||||
GQYDVQQDExJ3d3cuZG5zc2VjLWV4cC5vcmcxKDAmBgkqhkiG9w0BCQEWGWhvc3Rt
|
||||
YXN0ZXJAZG5zc2VjLWV4cC5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
|
||||
AoIBAQDEdF/22vaxrPbqpgVYMWi+alfpzBctpbfLBdPGuqOazJdCT0NbWcK8/+B4
|
||||
X6OlSOURNIlwLzhkmwVsWdVv6dVSaN7d4yI/fJkvgfDB9+au+iBJb6Pcz8ULBfe6
|
||||
D8HVvqKdORp6INzHz71z0sghxrQ0EAEkoWAZLh+kcn2ZHdcmZaBNUfjmGbyU6PRt
|
||||
RjdqoP+owIaC1aktBN7zl4uO7cRjlYFdusINrh2kPP02KAx2W84xjxX1uyj6oS6e
|
||||
7eBfvcwe8czW/N1rbE0CoR7h9+HnIrjnVG9RhBiZEiw3mUmF++Up26+4KTdRKbu3
|
||||
+BL4yMpfd66z0+zzqu+HkvyLpFn5AgMBAAGjggL/MIIC+zAJBgNVHRMEAjAAMAsG
|
||||
A1UdDwQEAwIDqDATBgNVHSUEDDAKBggrBgEFBQcDATAdBgNVHQ4EFgQUy04I5guM
|
||||
drzfh2JQaXhgV86+4jUwHwYDVR0jBBgwFoAU60I00Jiwq5/0G2sI98xkLu8OLEUw
|
||||
LQYDVR0RBCYwJIISd3d3LmRuc3NlYy1leHAub3Jngg5kbnNzZWMtZXhwLm9yZzCC
|
||||
AUIGA1UdIASCATkwggE1MIIBMQYLKwYBBAGBtTcBAgIwggEgMC4GCCsGAQUFBwIB
|
||||
FiJodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9wb2xpY3kucGRmMDQGCCsGAQUFBwIB
|
||||
FihodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9pbnRlcm1lZGlhdGUucGRmMIG3Bggr
|
||||
BgEFBQcCAjCBqjAUFg1TdGFydENvbSBMdGQuMAMCAQEagZFMaW1pdGVkIExpYWJp
|
||||
bGl0eSwgc2VlIHNlY3Rpb24gKkxlZ2FsIExpbWl0YXRpb25zKiBvZiB0aGUgU3Rh
|
||||
cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUG9saWN5IGF2YWlsYWJsZSBh
|
||||
dCBodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9wb2xpY3kucGRmMGEGA1UdHwRaMFgw
|
||||
KqAooCaGJGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2NydDEtY3JsLmNybDAqoCig
|
||||
JoYkaHR0cDovL2NybC5zdGFydHNzbC5jb20vY3J0MS1jcmwuY3JsMIGOBggrBgEF
|
||||
BQcBAQSBgTB/MDkGCCsGAQUFBzABhi1odHRwOi8vb2NzcC5zdGFydHNzbC5jb20v
|
||||
c3ViL2NsYXNzMS9zZXJ2ZXIvY2EwQgYIKwYBBQUHMAKGNmh0dHA6Ly93d3cuc3Rh
|
||||
cnRzc2wuY29tL2NlcnRzL3N1Yi5jbGFzczEuc2VydmVyLmNhLmNydDAjBgNVHRIE
|
||||
HDAahhhodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS8wDQYJKoZIhvcNAQEFBQADggEB
|
||||
ACXj6SB59KRJPenn6gUdGEqcta97U769SATyiQ87i9er64qLwvIGLMa3o2Rcgl2Y
|
||||
kghUeyLdN/EXyFBYA8L8uvZREPoc7EZukpT/ZDLXy9i2S0jkOxvF2fD/XLbcjGjM
|
||||
iEYG1/6ASw0ri9C0k4oDDoJLCoeH9++yqF7SFCCMcDkJqiAGXNb4euDpa8vCCtEQ
|
||||
CSS+ObZbfkreRt3cNCf5LfCXe9OsTnCfc8Cuq81c0oLaG+SmaLUQNBuToq8e9/Zm
|
||||
+b+/a3RVjxmkV5OCcGVBxsXNDn54Q6wsdw0TBMcjwoEndzpLS7yWgFbbkq5ZiGpw
|
||||
Qibb2+CfKuQ+WFV1GkVQmVA=
|
||||
-----END CERTIFICATE-----`
|
||||
|
||||
const startComIntermediate = `-----BEGIN CERTIFICATE-----
|
||||
MIIGNDCCBBygAwIBAgIBGDANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW
|
||||
MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
|
||||
Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
|
||||
dGlvbiBBdXRob3JpdHkwHhcNMDcxMDI0MjA1NDE3WhcNMTcxMDI0MjA1NDE3WjCB
|
||||
jDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKzApBgNVBAsT
|
||||
IlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcxODA2BgNVBAMTL1N0
|
||||
YXJ0Q29tIENsYXNzIDEgUHJpbWFyeSBJbnRlcm1lZGlhdGUgU2VydmVyIENBMIIB
|
||||
IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtonGrO8JUngHrJJj0PREGBiE
|
||||
gFYfka7hh/oyULTTRwbw5gdfcA4Q9x3AzhA2NIVaD5Ksg8asWFI/ujjo/OenJOJA
|
||||
pgh2wJJuniptTT9uYSAK21ne0n1jsz5G/vohURjXzTCm7QduO3CHtPn66+6CPAVv
|
||||
kvek3AowHpNz/gfK11+AnSJYUq4G2ouHI2mw5CrY6oPSvfNx23BaKA+vWjhwRRI/
|
||||
ME3NO68X5Q/LoKldSKqxYVDLNM08XMML6BDAjJvwAwNi/rJsPnIO7hxDKslIDlc5
|
||||
xDEhyBDBLIf+VJVSH1I8MRKbf+fAoKVZ1eKPPvDVqOHXcDGpxLPPr21TLwb0pwID
|
||||
AQABo4IBrTCCAakwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
|
||||
VR0OBBYEFOtCNNCYsKuf9BtrCPfMZC7vDixFMB8GA1UdIwQYMBaAFE4L7xqkQFul
|
||||
F2mHMMo0aEPQQa7yMGYGCCsGAQUFBwEBBFowWDAnBggrBgEFBQcwAYYbaHR0cDov
|
||||
L29jc3Auc3RhcnRzc2wuY29tL2NhMC0GCCsGAQUFBzAChiFodHRwOi8vd3d3LnN0
|
||||
YXJ0c3NsLmNvbS9zZnNjYS5jcnQwWwYDVR0fBFQwUjAnoCWgI4YhaHR0cDovL3d3
|
||||
dy5zdGFydHNzbC5jb20vc2ZzY2EuY3JsMCegJaAjhiFodHRwOi8vY3JsLnN0YXJ0
|
||||
c3NsLmNvbS9zZnNjYS5jcmwwgYAGA1UdIAR5MHcwdQYLKwYBBAGBtTcBAgEwZjAu
|
||||
BggrBgEFBQcCARYiaHR0cDovL3d3dy5zdGFydHNzbC5jb20vcG9saWN5LnBkZjA0
|
||||
BggrBgEFBQcCARYoaHR0cDovL3d3dy5zdGFydHNzbC5jb20vaW50ZXJtZWRpYXRl
|
||||
LnBkZjANBgkqhkiG9w0BAQUFAAOCAgEAIQlJPqWIbuALi0jaMU2P91ZXouHTYlfp
|
||||
tVbzhUV1O+VQHwSL5qBaPucAroXQ+/8gA2TLrQLhxpFy+KNN1t7ozD+hiqLjfDen
|
||||
xk+PNdb01m4Ge90h2c9W/8swIkn+iQTzheWq8ecf6HWQTd35RvdCNPdFWAwRDYSw
|
||||
xtpdPvkBnufh2lWVvnQce/xNFE+sflVHfXv0pQ1JHpXo9xLBzP92piVH0PN1Nb6X
|
||||
t1gW66pceG/sUzCv6gRNzKkC4/C2BBL2MLERPZBOVmTX3DxDX3M570uvh+v2/miI
|
||||
RHLq0gfGabDBoYvvF0nXYbFFSF87ICHpW7LM9NfpMfULFWE7epTj69m8f5SuauNi
|
||||
YpaoZHy4h/OZMn6SolK+u/hlz8nyMPyLwcKmltdfieFcNID1j0cHL7SRv7Gifl9L
|
||||
WtBbnySGBVFaaQNlQ0lxxeBvlDRr9hvYqbBMflPrj0jfyjO1SPo2ShpTpjMM0InN
|
||||
SRXNiTE8kMBy12VLUjWKRhFEuT2OKGWmPnmeXAhEKa2wNREuIU640ucQPl2Eg7PD
|
||||
wuTSxv0JS3QJ3fGz0xk+gA2iCxnwOOfFwq/iI9th4p1cbiCJSS4jarJiwUW0n6+L
|
||||
p/EiO/h94pDQehn7Skzj0n1fSoMD7SfWI55rjbRZotnvbIIp3XUZPD9MEI3vu3Un
|
||||
0q6Dp6jOW6c=
|
||||
-----END CERTIFICATE-----`
|
||||
|
||||
const startComRoot = `-----BEGIN CERTIFICATE-----
|
||||
MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW
|
||||
MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
|
||||
Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
|
||||
dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9
|
||||
MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi
|
||||
U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh
|
||||
cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA
|
||||
A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk
|
||||
pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf
|
||||
OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C
|
||||
Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT
|
||||
Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi
|
||||
HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM
|
||||
Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w
|
||||
+2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+
|
||||
Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3
|
||||
Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B
|
||||
26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID
|
||||
AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE
|
||||
FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j
|
||||
ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js
|
||||
LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM
|
||||
BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0
|
||||
Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy
|
||||
dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh
|
||||
cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh
|
||||
YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg
|
||||
dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp
|
||||
bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ
|
||||
YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT
|
||||
TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ
|
||||
9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8
|
||||
jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW
|
||||
FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz
|
||||
ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1
|
||||
ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L
|
||||
EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu
|
||||
L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq
|
||||
yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC
|
||||
O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V
|
||||
um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh
|
||||
NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14=
|
||||
-----END CERTIFICATE-----`
|
@ -2,12 +2,13 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This package parses X.509-encoded keys and certificates.
|
||||
// Package x509 parses X.509-encoded keys and certificates.
|
||||
package x509
|
||||
|
||||
import (
|
||||
"asn1"
|
||||
"big"
|
||||
"bytes"
|
||||
"container/vector"
|
||||
"crypto"
|
||||
"crypto/rsa"
|
||||
@ -15,7 +16,6 @@ import (
|
||||
"hash"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -27,6 +27,20 @@ type pkcs1PrivateKey struct {
|
||||
D asn1.RawValue
|
||||
P asn1.RawValue
|
||||
Q asn1.RawValue
|
||||
// We ignore these values, if present, because rsa will calculate them.
|
||||
Dp asn1.RawValue "optional"
|
||||
Dq asn1.RawValue "optional"
|
||||
Qinv asn1.RawValue "optional"
|
||||
|
||||
AdditionalPrimes []pkcs1AddtionalRSAPrime "optional"
|
||||
}
|
||||
|
||||
type pkcs1AddtionalRSAPrime struct {
|
||||
Prime asn1.RawValue
|
||||
|
||||
// We ignore these values because rsa will calculate them.
|
||||
Exp asn1.RawValue
|
||||
Coeff asn1.RawValue
|
||||
}
|
||||
|
||||
// rawValueIsInteger returns true iff the given ASN.1 RawValue is an INTEGER type.
|
||||
@ -46,6 +60,10 @@ func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err os.Error) {
|
||||
return
|
||||
}
|
||||
|
||||
if priv.Version > 1 {
|
||||
return nil, os.ErrorString("x509: unsupported private key version")
|
||||
}
|
||||
|
||||
if !rawValueIsInteger(&priv.N) ||
|
||||
!rawValueIsInteger(&priv.D) ||
|
||||
!rawValueIsInteger(&priv.P) ||
|
||||
@ -61,26 +79,66 @@ func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err os.Error) {
|
||||
}
|
||||
|
||||
key.D = new(big.Int).SetBytes(priv.D.Bytes)
|
||||
key.P = new(big.Int).SetBytes(priv.P.Bytes)
|
||||
key.Q = new(big.Int).SetBytes(priv.Q.Bytes)
|
||||
key.Primes = make([]*big.Int, 2+len(priv.AdditionalPrimes))
|
||||
key.Primes[0] = new(big.Int).SetBytes(priv.P.Bytes)
|
||||
key.Primes[1] = new(big.Int).SetBytes(priv.Q.Bytes)
|
||||
for i, a := range priv.AdditionalPrimes {
|
||||
if !rawValueIsInteger(&a.Prime) {
|
||||
return nil, asn1.StructuralError{"tags don't match"}
|
||||
}
|
||||
key.Primes[i+2] = new(big.Int).SetBytes(a.Prime.Bytes)
|
||||
// We ignore the other two values because rsa will calculate
|
||||
// them as needed.
|
||||
}
|
||||
|
||||
err = key.Validate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key.Precompute()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// rawValueForBig returns an asn1.RawValue which represents the given integer.
|
||||
func rawValueForBig(n *big.Int) asn1.RawValue {
|
||||
b := n.Bytes()
|
||||
if n.Sign() >= 0 && len(b) > 0 && b[0]&0x80 != 0 {
|
||||
// This positive number would be interpreted as a negative
|
||||
// number in ASN.1 because the MSB is set.
|
||||
padded := make([]byte, len(b)+1)
|
||||
copy(padded[1:], b)
|
||||
b = padded
|
||||
}
|
||||
return asn1.RawValue{Tag: 2, Bytes: b}
|
||||
}
|
||||
|
||||
// MarshalPKCS1PrivateKey converts a private key to ASN.1 DER encoded form.
|
||||
func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte {
|
||||
key.Precompute()
|
||||
|
||||
version := 0
|
||||
if len(key.Primes) > 2 {
|
||||
version = 1
|
||||
}
|
||||
|
||||
priv := pkcs1PrivateKey{
|
||||
Version: 1,
|
||||
N: asn1.RawValue{Tag: 2, Bytes: key.PublicKey.N.Bytes()},
|
||||
Version: version,
|
||||
N: rawValueForBig(key.N),
|
||||
E: key.PublicKey.E,
|
||||
D: asn1.RawValue{Tag: 2, Bytes: key.D.Bytes()},
|
||||
P: asn1.RawValue{Tag: 2, Bytes: key.P.Bytes()},
|
||||
Q: asn1.RawValue{Tag: 2, Bytes: key.Q.Bytes()},
|
||||
D: rawValueForBig(key.D),
|
||||
P: rawValueForBig(key.Primes[0]),
|
||||
Q: rawValueForBig(key.Primes[1]),
|
||||
Dp: rawValueForBig(key.Precomputed.Dp),
|
||||
Dq: rawValueForBig(key.Precomputed.Dq),
|
||||
Qinv: rawValueForBig(key.Precomputed.Qinv),
|
||||
}
|
||||
|
||||
priv.AdditionalPrimes = make([]pkcs1AddtionalRSAPrime, len(key.Precomputed.CRTValues))
|
||||
for i, values := range key.Precomputed.CRTValues {
|
||||
priv.AdditionalPrimes[i].Prime = rawValueForBig(key.Primes[2+i])
|
||||
priv.AdditionalPrimes[i].Exp = rawValueForBig(values.Exp)
|
||||
priv.AdditionalPrimes[i].Coeff = rawValueForBig(values.Coeff)
|
||||
}
|
||||
|
||||
b, _ := asn1.Marshal(priv)
|
||||
@ -90,6 +148,7 @@ func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte {
|
||||
// These structures reflect the ASN.1 structure of X.509 certificates.:
|
||||
|
||||
type certificate struct {
|
||||
Raw asn1.RawContent
|
||||
TBSCertificate tbsCertificate
|
||||
SignatureAlgorithm algorithmIdentifier
|
||||
SignatureValue asn1.BitString
|
||||
@ -127,6 +186,7 @@ type validity struct {
|
||||
}
|
||||
|
||||
type publicKeyInfo struct {
|
||||
Raw asn1.RawContent
|
||||
Algorithm algorithmIdentifier
|
||||
PublicKey asn1.BitString
|
||||
}
|
||||
@ -343,7 +403,10 @@ const (
|
||||
|
||||
// A Certificate represents an X.509 certificate.
|
||||
type Certificate struct {
|
||||
Raw []byte // Raw ASN.1 DER contents.
|
||||
Raw []byte // Complete ASN.1 DER content (certificate, signature algorithm and signature).
|
||||
RawTBSCertificate []byte // Certificate part of raw ASN.1 DER content.
|
||||
RawSubjectPublicKeyInfo []byte // DER encoded SubjectPublicKeyInfo.
|
||||
|
||||
Signature []byte
|
||||
SignatureAlgorithm SignatureAlgorithm
|
||||
|
||||
@ -395,6 +458,10 @@ func (ConstraintViolationError) String() string {
|
||||
return "invalid signature: parent certificate cannot sign this kind of certificate"
|
||||
}
|
||||
|
||||
func (c *Certificate) Equal(other *Certificate) bool {
|
||||
return bytes.Equal(c.Raw, other.Raw)
|
||||
}
|
||||
|
||||
// CheckSignatureFrom verifies that the signature on c is a valid signature
|
||||
// from parent.
|
||||
func (c *Certificate) CheckSignatureFrom(parent *Certificate) (err os.Error) {
|
||||
@ -434,69 +501,12 @@ func (c *Certificate) CheckSignatureFrom(parent *Certificate) (err os.Error) {
|
||||
return UnsupportedAlgorithmError{}
|
||||
}
|
||||
|
||||
h.Write(c.Raw)
|
||||
h.Write(c.RawTBSCertificate)
|
||||
digest := h.Sum()
|
||||
|
||||
return rsa.VerifyPKCS1v15(pub, hashType, digest, c.Signature)
|
||||
}
|
||||
|
||||
func matchHostnames(pattern, host string) bool {
|
||||
if len(pattern) == 0 || len(host) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
patternParts := strings.Split(pattern, ".", -1)
|
||||
hostParts := strings.Split(host, ".", -1)
|
||||
|
||||
if len(patternParts) != len(hostParts) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i, patternPart := range patternParts {
|
||||
if patternPart == "*" {
|
||||
continue
|
||||
}
|
||||
if patternPart != hostParts[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
type HostnameError struct {
|
||||
Certificate *Certificate
|
||||
Host string
|
||||
}
|
||||
|
||||
func (h *HostnameError) String() string {
|
||||
var valid string
|
||||
c := h.Certificate
|
||||
if len(c.DNSNames) > 0 {
|
||||
valid = strings.Join(c.DNSNames, ", ")
|
||||
} else {
|
||||
valid = c.Subject.CommonName
|
||||
}
|
||||
return "certificate is valid for " + valid + ", not " + h.Host
|
||||
}
|
||||
|
||||
// VerifyHostname returns nil if c is a valid certificate for the named host.
|
||||
// Otherwise it returns an os.Error describing the mismatch.
|
||||
func (c *Certificate) VerifyHostname(h string) os.Error {
|
||||
if len(c.DNSNames) > 0 {
|
||||
for _, match := range c.DNSNames {
|
||||
if matchHostnames(match, h) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
// If Subject Alt Name is given, we ignore the common name.
|
||||
} else if matchHostnames(c.Subject.CommonName, h) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &HostnameError{c, h}
|
||||
}
|
||||
|
||||
type UnhandledCriticalExtension struct{}
|
||||
|
||||
func (h UnhandledCriticalExtension) String() string {
|
||||
@ -558,7 +568,9 @@ func parsePublicKey(algo PublicKeyAlgorithm, asn1Data []byte) (interface{}, os.E
|
||||
|
||||
func parseCertificate(in *certificate) (*Certificate, os.Error) {
|
||||
out := new(Certificate)
|
||||
out.Raw = in.TBSCertificate.Raw
|
||||
out.Raw = in.Raw
|
||||
out.RawTBSCertificate = in.TBSCertificate.Raw
|
||||
out.RawSubjectPublicKeyInfo = in.TBSCertificate.PublicKey.Raw
|
||||
|
||||
out.Signature = in.SignatureValue.RightAlign()
|
||||
out.SignatureAlgorithm =
|
||||
@ -975,7 +987,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub *rsa.P
|
||||
Issuer: parent.Subject.toRDNSequence(),
|
||||
Validity: validity{template.NotBefore, template.NotAfter},
|
||||
Subject: template.Subject.toRDNSequence(),
|
||||
PublicKey: publicKeyInfo{algorithmIdentifier{oidRSA}, encodedPublicKey},
|
||||
PublicKey: publicKeyInfo{nil, algorithmIdentifier{oidRSA}, encodedPublicKey},
|
||||
Extensions: extensions,
|
||||
}
|
||||
|
||||
@ -996,6 +1008,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub *rsa.P
|
||||
}
|
||||
|
||||
cert, err = asn1.Marshal(certificate{
|
||||
nil,
|
||||
c,
|
||||
algorithmIdentifier{oidSHA1WithRSA},
|
||||
asn1.BitString{Bytes: signature, BitLength: len(signature) * 8},
|
||||
|
@ -20,12 +20,13 @@ func TestParsePKCS1PrivateKey(t *testing.T) {
|
||||
priv, err := ParsePKCS1PrivateKey(block.Bytes)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to parse private key: %s", err)
|
||||
return
|
||||
}
|
||||
if priv.PublicKey.N.Cmp(rsaPrivateKey.PublicKey.N) != 0 ||
|
||||
priv.PublicKey.E != rsaPrivateKey.PublicKey.E ||
|
||||
priv.D.Cmp(rsaPrivateKey.D) != 0 ||
|
||||
priv.P.Cmp(rsaPrivateKey.P) != 0 ||
|
||||
priv.Q.Cmp(rsaPrivateKey.Q) != 0 {
|
||||
priv.Primes[0].Cmp(rsaPrivateKey.Primes[0]) != 0 ||
|
||||
priv.Primes[1].Cmp(rsaPrivateKey.Primes[1]) != 0 {
|
||||
t.Errorf("got:%+v want:%+v", priv, rsaPrivateKey)
|
||||
}
|
||||
}
|
||||
@ -47,14 +48,54 @@ func bigFromString(s string) *big.Int {
|
||||
return ret
|
||||
}
|
||||
|
||||
func fromBase10(base10 string) *big.Int {
|
||||
i := new(big.Int)
|
||||
i.SetString(base10, 10)
|
||||
return i
|
||||
}
|
||||
|
||||
var rsaPrivateKey = &rsa.PrivateKey{
|
||||
PublicKey: rsa.PublicKey{
|
||||
N: bigFromString("9353930466774385905609975137998169297361893554149986716853295022578535724979677252958524466350471210367835187480748268864277464700638583474144061408845077"),
|
||||
E: 65537,
|
||||
},
|
||||
D: bigFromString("7266398431328116344057699379749222532279343923819063639497049039389899328538543087657733766554155839834519529439851673014800261285757759040931985506583861"),
|
||||
P: bigFromString("98920366548084643601728869055592650835572950932266967461790948584315647051443"),
|
||||
Q: bigFromString("94560208308847015747498523884063394671606671904944666360068158221458669711639"),
|
||||
Primes: []*big.Int{
|
||||
bigFromString("98920366548084643601728869055592650835572950932266967461790948584315647051443"),
|
||||
bigFromString("94560208308847015747498523884063394671606671904944666360068158221458669711639"),
|
||||
},
|
||||
}
|
||||
|
||||
func TestMarshalRSAPrivateKey(t *testing.T) {
|
||||
priv := &rsa.PrivateKey{
|
||||
PublicKey: rsa.PublicKey{
|
||||
N: fromBase10("16346378922382193400538269749936049106320265317511766357599732575277382844051791096569333808598921852351577762718529818072849191122419410612033592401403764925096136759934497687765453905884149505175426053037420486697072448609022753683683718057795566811401938833367954642951433473337066311978821180526439641496973296037000052546108507805269279414789035461158073156772151892452251106173507240488993608650881929629163465099476849643165682709047462010581308719577053905787496296934240246311806555924593059995202856826239801816771116902778517096212527979497399966526283516447337775509777558018145573127308919204297111496233"),
|
||||
E: 3,
|
||||
},
|
||||
D: fromBase10("10897585948254795600358846499957366070880176878341177571733155050184921896034527397712889205732614568234385175145686545381899460748279607074689061600935843283397424506622998458510302603922766336783617368686090042765718290914099334449154829375179958369993407724946186243249568928237086215759259909861748642124071874879861299389874230489928271621259294894142840428407196932444474088857746123104978617098858619445675532587787023228852383149557470077802718705420275739737958953794088728369933811184572620857678792001136676902250566845618813972833750098806496641114644760255910789397593428910198080271317419213080834885003"),
|
||||
Primes: []*big.Int{
|
||||
fromBase10("1025363189502892836833747188838978207017355117492483312747347695538428729137306368764177201532277413433182799108299960196606011786562992097313508180436744488171474690412562218914213688661311117337381958560443"),
|
||||
fromBase10("3467903426626310123395340254094941045497208049900750380025518552334536945536837294961497712862519984786362199788654739924501424784631315081391467293694361474867825728031147665777546570788493758372218019373"),
|
||||
fromBase10("4597024781409332673052708605078359346966325141767460991205742124888960305710298765592730135879076084498363772408626791576005136245060321874472727132746643162385746062759369754202494417496879741537284589047"),
|
||||
},
|
||||
}
|
||||
|
||||
derBytes := MarshalPKCS1PrivateKey(priv)
|
||||
|
||||
priv2, err := ParsePKCS1PrivateKey(derBytes)
|
||||
if err != nil {
|
||||
t.Errorf("error parsing serialized key: %s", err)
|
||||
return
|
||||
}
|
||||
if priv.PublicKey.N.Cmp(priv2.PublicKey.N) != 0 ||
|
||||
priv.PublicKey.E != priv2.PublicKey.E ||
|
||||
priv.D.Cmp(priv2.D) != 0 ||
|
||||
len(priv2.Primes) != 3 ||
|
||||
priv.Primes[0].Cmp(priv2.Primes[0]) != 0 ||
|
||||
priv.Primes[1].Cmp(priv2.Primes[1]) != 0 ||
|
||||
priv.Primes[2].Cmp(priv2.Primes[2]) != 0 {
|
||||
t.Errorf("got:%+v want:%+v", priv, priv2)
|
||||
}
|
||||
}
|
||||
|
||||
type matchHostnamesTest struct {
|
||||
|
@ -2,8 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This package implements XTEA encryption, as defined in Needham and
|
||||
// Wheeler's 1997 technical report, "Tea extensions."
|
||||
// Package xtea implements XTEA encryption, as defined in Needham and Wheeler's
|
||||
// 1997 technical report, "Tea extensions."
|
||||
package xtea
|
||||
|
||||
// For details, see http://www.cix.co.uk/~klockstone/xtea.pdf
|
||||
|
@ -2,9 +2,9 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This package provides access to DWARF debugging information
|
||||
// loaded from executable files, as defined in the DWARF 2.0 Standard
|
||||
// at http://dwarfstd.org/doc/dwarf-2.0.0.pdf
|
||||
// Package dwarf provides access to DWARF debugging information loaded from
|
||||
// executable files, as defined in the DWARF 2.0 Standard at
|
||||
// http://dwarfstd.org/doc/dwarf-2.0.0.pdf
|
||||
package dwarf
|
||||
|
||||
import (
|
||||
|
@ -330,29 +330,35 @@ func (i SectionIndex) GoString() string { return stringName(uint32(i), shnString
|
||||
type SectionType uint32
|
||||
|
||||
const (
|
||||
SHT_NULL SectionType = 0 /* inactive */
|
||||
SHT_PROGBITS SectionType = 1 /* program defined information */
|
||||
SHT_SYMTAB SectionType = 2 /* symbol table section */
|
||||
SHT_STRTAB SectionType = 3 /* string table section */
|
||||
SHT_RELA SectionType = 4 /* relocation section with addends */
|
||||
SHT_HASH SectionType = 5 /* symbol hash table section */
|
||||
SHT_DYNAMIC SectionType = 6 /* dynamic section */
|
||||
SHT_NOTE SectionType = 7 /* note section */
|
||||
SHT_NOBITS SectionType = 8 /* no space section */
|
||||
SHT_REL SectionType = 9 /* relocation section - no addends */
|
||||
SHT_SHLIB SectionType = 10 /* reserved - purpose unknown */
|
||||
SHT_DYNSYM SectionType = 11 /* dynamic symbol table section */
|
||||
SHT_INIT_ARRAY SectionType = 14 /* Initialization function pointers. */
|
||||
SHT_FINI_ARRAY SectionType = 15 /* Termination function pointers. */
|
||||
SHT_PREINIT_ARRAY SectionType = 16 /* Pre-initialization function ptrs. */
|
||||
SHT_GROUP SectionType = 17 /* Section group. */
|
||||
SHT_SYMTAB_SHNDX SectionType = 18 /* Section indexes (see SHN_XINDEX). */
|
||||
SHT_LOOS SectionType = 0x60000000 /* First of OS specific semantics */
|
||||
SHT_HIOS SectionType = 0x6fffffff /* Last of OS specific semantics */
|
||||
SHT_LOPROC SectionType = 0x70000000 /* reserved range for processor */
|
||||
SHT_HIPROC SectionType = 0x7fffffff /* specific section header types */
|
||||
SHT_LOUSER SectionType = 0x80000000 /* reserved range for application */
|
||||
SHT_HIUSER SectionType = 0xffffffff /* specific indexes */
|
||||
SHT_NULL SectionType = 0 /* inactive */
|
||||
SHT_PROGBITS SectionType = 1 /* program defined information */
|
||||
SHT_SYMTAB SectionType = 2 /* symbol table section */
|
||||
SHT_STRTAB SectionType = 3 /* string table section */
|
||||
SHT_RELA SectionType = 4 /* relocation section with addends */
|
||||
SHT_HASH SectionType = 5 /* symbol hash table section */
|
||||
SHT_DYNAMIC SectionType = 6 /* dynamic section */
|
||||
SHT_NOTE SectionType = 7 /* note section */
|
||||
SHT_NOBITS SectionType = 8 /* no space section */
|
||||
SHT_REL SectionType = 9 /* relocation section - no addends */
|
||||
SHT_SHLIB SectionType = 10 /* reserved - purpose unknown */
|
||||
SHT_DYNSYM SectionType = 11 /* dynamic symbol table section */
|
||||
SHT_INIT_ARRAY SectionType = 14 /* Initialization function pointers. */
|
||||
SHT_FINI_ARRAY SectionType = 15 /* Termination function pointers. */
|
||||
SHT_PREINIT_ARRAY SectionType = 16 /* Pre-initialization function ptrs. */
|
||||
SHT_GROUP SectionType = 17 /* Section group. */
|
||||
SHT_SYMTAB_SHNDX SectionType = 18 /* Section indexes (see SHN_XINDEX). */
|
||||
SHT_LOOS SectionType = 0x60000000 /* First of OS specific semantics */
|
||||
SHT_GNU_ATTRIBUTES SectionType = 0x6ffffff5 /* GNU object attributes */
|
||||
SHT_GNU_HASH SectionType = 0x6ffffff6 /* GNU hash table */
|
||||
SHT_GNU_LIBLIST SectionType = 0x6ffffff7 /* GNU prelink library list */
|
||||
SHT_GNU_VERDEF SectionType = 0x6ffffffd /* GNU version definition section */
|
||||
SHT_GNU_VERNEED SectionType = 0x6ffffffe /* GNU version needs section */
|
||||
SHT_GNU_VERSYM SectionType = 0x6fffffff /* GNU version symbol table */
|
||||
SHT_HIOS SectionType = 0x6fffffff /* Last of OS specific semantics */
|
||||
SHT_LOPROC SectionType = 0x70000000 /* reserved range for processor */
|
||||
SHT_HIPROC SectionType = 0x7fffffff /* specific section header types */
|
||||
SHT_LOUSER SectionType = 0x80000000 /* reserved range for application */
|
||||
SHT_HIUSER SectionType = 0xffffffff /* specific indexes */
|
||||
)
|
||||
|
||||
var shtStrings = []intName{
|
||||
@ -374,7 +380,12 @@ var shtStrings = []intName{
|
||||
{17, "SHT_GROUP"},
|
||||
{18, "SHT_SYMTAB_SHNDX"},
|
||||
{0x60000000, "SHT_LOOS"},
|
||||
{0x6fffffff, "SHT_HIOS"},
|
||||
{0x6ffffff5, "SHT_GNU_ATTRIBUTES"},
|
||||
{0x6ffffff6, "SHT_GNU_HASH"},
|
||||
{0x6ffffff7, "SHT_GNU_LIBLIST"},
|
||||
{0x6ffffffd, "SHT_GNU_VERDEF"},
|
||||
{0x6ffffffe, "SHT_GNU_VERNEED"},
|
||||
{0x6fffffff, "SHT_GNU_VERSYM"},
|
||||
{0x70000000, "SHT_LOPROC"},
|
||||
{0x7fffffff, "SHT_HIPROC"},
|
||||
{0x80000000, "SHT_LOUSER"},
|
||||
@ -518,6 +529,9 @@ const (
|
||||
DT_PREINIT_ARRAYSZ DynTag = 33 /* Size in bytes of the array of pre-initialization functions. */
|
||||
DT_LOOS DynTag = 0x6000000d /* First OS-specific */
|
||||
DT_HIOS DynTag = 0x6ffff000 /* Last OS-specific */
|
||||
DT_VERSYM DynTag = 0x6ffffff0
|
||||
DT_VERNEED DynTag = 0x6ffffffe
|
||||
DT_VERNEEDNUM DynTag = 0x6fffffff
|
||||
DT_LOPROC DynTag = 0x70000000 /* First processor-specific type. */
|
||||
DT_HIPROC DynTag = 0x7fffffff /* Last processor-specific type. */
|
||||
)
|
||||
@ -559,6 +573,9 @@ var dtStrings = []intName{
|
||||
{33, "DT_PREINIT_ARRAYSZ"},
|
||||
{0x6000000d, "DT_LOOS"},
|
||||
{0x6ffff000, "DT_HIOS"},
|
||||
{0x6ffffff0, "DT_VERSYM"},
|
||||
{0x6ffffffe, "DT_VERNEED"},
|
||||
{0x6fffffff, "DT_VERNEEDNUM"},
|
||||
{0x70000000, "DT_LOPROC"},
|
||||
{0x7fffffff, "DT_HIPROC"},
|
||||
}
|
||||
|
@ -35,9 +35,11 @@ type FileHeader struct {
|
||||
// A File represents an open ELF file.
|
||||
type File struct {
|
||||
FileHeader
|
||||
Sections []*Section
|
||||
Progs []*Prog
|
||||
closer io.Closer
|
||||
Sections []*Section
|
||||
Progs []*Prog
|
||||
closer io.Closer
|
||||
gnuNeed []verneed
|
||||
gnuVersym []byte
|
||||
}
|
||||
|
||||
// A SectionHeader represents a single ELF section header.
|
||||
@ -329,8 +331,8 @@ func NewFile(r io.ReaderAt) (*File, os.Error) {
|
||||
}
|
||||
|
||||
// getSymbols returns a slice of Symbols from parsing the symbol table
|
||||
// with the given type.
|
||||
func (f *File) getSymbols(typ SectionType) ([]Symbol, os.Error) {
|
||||
// with the given type, along with the associated string table.
|
||||
func (f *File) getSymbols(typ SectionType) ([]Symbol, []byte, os.Error) {
|
||||
switch f.Class {
|
||||
case ELFCLASS64:
|
||||
return f.getSymbols64(typ)
|
||||
@ -339,27 +341,27 @@ func (f *File) getSymbols(typ SectionType) ([]Symbol, os.Error) {
|
||||
return f.getSymbols32(typ)
|
||||
}
|
||||
|
||||
return nil, os.ErrorString("not implemented")
|
||||
return nil, nil, os.ErrorString("not implemented")
|
||||
}
|
||||
|
||||
func (f *File) getSymbols32(typ SectionType) ([]Symbol, os.Error) {
|
||||
func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, os.Error) {
|
||||
symtabSection := f.SectionByType(typ)
|
||||
if symtabSection == nil {
|
||||
return nil, os.ErrorString("no symbol section")
|
||||
return nil, nil, os.ErrorString("no symbol section")
|
||||
}
|
||||
|
||||
data, err := symtabSection.Data()
|
||||
if err != nil {
|
||||
return nil, os.ErrorString("cannot load symbol section")
|
||||
return nil, nil, os.ErrorString("cannot load symbol section")
|
||||
}
|
||||
symtab := bytes.NewBuffer(data)
|
||||
if symtab.Len()%Sym32Size != 0 {
|
||||
return nil, os.ErrorString("length of symbol section is not a multiple of SymSize")
|
||||
return nil, nil, os.ErrorString("length of symbol section is not a multiple of SymSize")
|
||||
}
|
||||
|
||||
strdata, err := f.stringTable(symtabSection.Link)
|
||||
if err != nil {
|
||||
return nil, os.ErrorString("cannot load string table section")
|
||||
return nil, nil, os.ErrorString("cannot load string table section")
|
||||
}
|
||||
|
||||
// The first entry is all zeros.
|
||||
@ -382,27 +384,27 @@ func (f *File) getSymbols32(typ SectionType) ([]Symbol, os.Error) {
|
||||
i++
|
||||
}
|
||||
|
||||
return symbols, nil
|
||||
return symbols, strdata, nil
|
||||
}
|
||||
|
||||
func (f *File) getSymbols64(typ SectionType) ([]Symbol, os.Error) {
|
||||
func (f *File) getSymbols64(typ SectionType) ([]Symbol, []byte, os.Error) {
|
||||
symtabSection := f.SectionByType(typ)
|
||||
if symtabSection == nil {
|
||||
return nil, os.ErrorString("no symbol section")
|
||||
return nil, nil, os.ErrorString("no symbol section")
|
||||
}
|
||||
|
||||
data, err := symtabSection.Data()
|
||||
if err != nil {
|
||||
return nil, os.ErrorString("cannot load symbol section")
|
||||
return nil, nil, os.ErrorString("cannot load symbol section")
|
||||
}
|
||||
symtab := bytes.NewBuffer(data)
|
||||
if symtab.Len()%Sym64Size != 0 {
|
||||
return nil, os.ErrorString("length of symbol section is not a multiple of Sym64Size")
|
||||
return nil, nil, os.ErrorString("length of symbol section is not a multiple of Sym64Size")
|
||||
}
|
||||
|
||||
strdata, err := f.stringTable(symtabSection.Link)
|
||||
if err != nil {
|
||||
return nil, os.ErrorString("cannot load string table section")
|
||||
return nil, nil, os.ErrorString("cannot load string table section")
|
||||
}
|
||||
|
||||
// The first entry is all zeros.
|
||||
@ -425,7 +427,7 @@ func (f *File) getSymbols64(typ SectionType) ([]Symbol, os.Error) {
|
||||
i++
|
||||
}
|
||||
|
||||
return symbols, nil
|
||||
return symbols, strdata, nil
|
||||
}
|
||||
|
||||
// getString extracts a string from an ELF string table.
|
||||
@ -468,7 +470,7 @@ func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) os.Error {
|
||||
return os.ErrorString("length of relocation section is not a multiple of Sym64Size")
|
||||
}
|
||||
|
||||
symbols, err := f.getSymbols(SHT_SYMTAB)
|
||||
symbols, _, err := f.getSymbols(SHT_SYMTAB)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -544,24 +546,123 @@ func (f *File) DWARF() (*dwarf.Data, os.Error) {
|
||||
return dwarf.New(abbrev, nil, nil, info, nil, nil, nil, str)
|
||||
}
|
||||
|
||||
type ImportedSymbol struct {
|
||||
Name string
|
||||
Version string
|
||||
Library string
|
||||
}
|
||||
|
||||
// ImportedSymbols returns the names of all symbols
|
||||
// referred to by the binary f that are expected to be
|
||||
// satisfied by other libraries at dynamic load time.
|
||||
// It does not return weak symbols.
|
||||
func (f *File) ImportedSymbols() ([]string, os.Error) {
|
||||
sym, err := f.getSymbols(SHT_DYNSYM)
|
||||
func (f *File) ImportedSymbols() ([]ImportedSymbol, os.Error) {
|
||||
sym, str, err := f.getSymbols(SHT_DYNSYM)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var all []string
|
||||
for _, s := range sym {
|
||||
f.gnuVersionInit(str)
|
||||
var all []ImportedSymbol
|
||||
for i, s := range sym {
|
||||
if ST_BIND(s.Info) == STB_GLOBAL && s.Section == SHN_UNDEF {
|
||||
all = append(all, s.Name)
|
||||
all = append(all, ImportedSymbol{Name: s.Name})
|
||||
f.gnuVersion(i, &all[len(all)-1])
|
||||
}
|
||||
}
|
||||
return all, nil
|
||||
}
|
||||
|
||||
type verneed struct {
|
||||
File string
|
||||
Name string
|
||||
}
|
||||
|
||||
// gnuVersionInit parses the GNU version tables
|
||||
// for use by calls to gnuVersion.
|
||||
func (f *File) gnuVersionInit(str []byte) {
|
||||
// Accumulate verneed information.
|
||||
vn := f.SectionByType(SHT_GNU_VERNEED)
|
||||
if vn == nil {
|
||||
return
|
||||
}
|
||||
d, _ := vn.Data()
|
||||
|
||||
var need []verneed
|
||||
i := 0
|
||||
for {
|
||||
if i+16 > len(d) {
|
||||
break
|
||||
}
|
||||
vers := f.ByteOrder.Uint16(d[i : i+2])
|
||||
if vers != 1 {
|
||||
break
|
||||
}
|
||||
cnt := f.ByteOrder.Uint16(d[i+2 : i+4])
|
||||
fileoff := f.ByteOrder.Uint32(d[i+4 : i+8])
|
||||
aux := f.ByteOrder.Uint32(d[i+8 : i+12])
|
||||
next := f.ByteOrder.Uint32(d[i+12 : i+16])
|
||||
file, _ := getString(str, int(fileoff))
|
||||
|
||||
var name string
|
||||
j := i + int(aux)
|
||||
for c := 0; c < int(cnt); c++ {
|
||||
if j+16 > len(d) {
|
||||
break
|
||||
}
|
||||
// hash := f.ByteOrder.Uint32(d[j:j+4])
|
||||
// flags := f.ByteOrder.Uint16(d[j+4:j+6])
|
||||
other := f.ByteOrder.Uint16(d[j+6 : j+8])
|
||||
nameoff := f.ByteOrder.Uint32(d[j+8 : j+12])
|
||||
next := f.ByteOrder.Uint32(d[j+12 : j+16])
|
||||
name, _ = getString(str, int(nameoff))
|
||||
ndx := int(other)
|
||||
if ndx >= len(need) {
|
||||
a := make([]verneed, 2*(ndx+1))
|
||||
copy(a, need)
|
||||
need = a
|
||||
}
|
||||
|
||||
need[ndx] = verneed{file, name}
|
||||
if next == 0 {
|
||||
break
|
||||
}
|
||||
j += int(next)
|
||||
}
|
||||
|
||||
if next == 0 {
|
||||
break
|
||||
}
|
||||
i += int(next)
|
||||
}
|
||||
|
||||
// Versym parallels symbol table, indexing into verneed.
|
||||
vs := f.SectionByType(SHT_GNU_VERSYM)
|
||||
if vs == nil {
|
||||
return
|
||||
}
|
||||
d, _ = vs.Data()
|
||||
|
||||
f.gnuNeed = need
|
||||
f.gnuVersym = d
|
||||
}
|
||||
|
||||
// gnuVersion adds Library and Version information to sym,
|
||||
// which came from offset i of the symbol table.
|
||||
func (f *File) gnuVersion(i int, sym *ImportedSymbol) {
|
||||
// Each entry is two bytes; skip undef entry at beginning.
|
||||
i = (i + 1) * 2
|
||||
if i >= len(f.gnuVersym) {
|
||||
return
|
||||
}
|
||||
j := int(f.ByteOrder.Uint16(f.gnuVersym[i:]))
|
||||
if j < 2 || j >= len(f.gnuNeed) {
|
||||
return
|
||||
}
|
||||
n := &f.gnuNeed[j]
|
||||
sym.Library = n.File
|
||||
sym.Version = n.Name
|
||||
}
|
||||
|
||||
// ImportedLibraries returns the names of all libraries
|
||||
// referred to by the binary f that are expected to be
|
||||
// linked with the binary at dynamic link time.
|
||||
|
@ -2,8 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// A library for EBNF grammars. The input is text ([]byte) satisfying
|
||||
// the following grammar (represented itself in EBNF):
|
||||
// Package ebnf is a library for EBNF grammars. The input is text ([]byte)
|
||||
// satisfying the following grammar (represented itself in EBNF):
|
||||
//
|
||||
// Production = name "=" Expression "." .
|
||||
// Expression = Alternative { "|" Alternative } .
|
||||
|
@ -126,10 +126,10 @@ func (bigEndian) GoString() string { return "binary.BigEndian" }
|
||||
// and written to successive fields of the data.
|
||||
func Read(r io.Reader, order ByteOrder, data interface{}) os.Error {
|
||||
var v reflect.Value
|
||||
switch d := reflect.NewValue(data).(type) {
|
||||
case *reflect.PtrValue:
|
||||
switch d := reflect.ValueOf(data); d.Kind() {
|
||||
case reflect.Ptr:
|
||||
v = d.Elem()
|
||||
case *reflect.SliceValue:
|
||||
case reflect.Slice:
|
||||
v = d
|
||||
default:
|
||||
return os.NewError("binary.Read: invalid type " + d.Type().String())
|
||||
@ -155,7 +155,7 @@ func Read(r io.Reader, order ByteOrder, data interface{}) os.Error {
|
||||
// Bytes written to w are encoded using the specified byte order
|
||||
// and read from successive fields of the data.
|
||||
func Write(w io.Writer, order ByteOrder, data interface{}) os.Error {
|
||||
v := reflect.Indirect(reflect.NewValue(data))
|
||||
v := reflect.Indirect(reflect.ValueOf(data))
|
||||
size := TotalSize(v)
|
||||
if size < 0 {
|
||||
return os.NewError("binary.Write: invalid type " + v.Type().String())
|
||||
@ -168,26 +168,26 @@ func Write(w io.Writer, order ByteOrder, data interface{}) os.Error {
|
||||
}
|
||||
|
||||
func TotalSize(v reflect.Value) int {
|
||||
if sv, ok := v.(*reflect.SliceValue); ok {
|
||||
elem := sizeof(v.Type().(*reflect.SliceType).Elem())
|
||||
if v.Kind() == reflect.Slice {
|
||||
elem := sizeof(v.Type().Elem())
|
||||
if elem < 0 {
|
||||
return -1
|
||||
}
|
||||
return sv.Len() * elem
|
||||
return v.Len() * elem
|
||||
}
|
||||
return sizeof(v.Type())
|
||||
}
|
||||
|
||||
func sizeof(v reflect.Type) int {
|
||||
switch t := v.(type) {
|
||||
case *reflect.ArrayType:
|
||||
func sizeof(t reflect.Type) int {
|
||||
switch t.Kind() {
|
||||
case reflect.Array:
|
||||
n := sizeof(t.Elem())
|
||||
if n < 0 {
|
||||
return -1
|
||||
}
|
||||
return t.Len() * n
|
||||
|
||||
case *reflect.StructType:
|
||||
case reflect.Struct:
|
||||
sum := 0
|
||||
for i, n := 0, t.NumField(); i < n; i++ {
|
||||
s := sizeof(t.Field(i).Type)
|
||||
@ -198,12 +198,10 @@ func sizeof(v reflect.Type) int {
|
||||
}
|
||||
return sum
|
||||
|
||||
case *reflect.UintType, *reflect.IntType, *reflect.FloatType, *reflect.ComplexType:
|
||||
switch t := t.Kind(); t {
|
||||
case reflect.Int, reflect.Uint, reflect.Uintptr:
|
||||
return -1
|
||||
}
|
||||
return int(v.Size())
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
|
||||
reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||
reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128:
|
||||
return int(t.Size())
|
||||
}
|
||||
return -1
|
||||
}
|
||||
@ -279,130 +277,118 @@ func (d *decoder) int64() int64 { return int64(d.uint64()) }
|
||||
func (e *encoder) int64(x int64) { e.uint64(uint64(x)) }
|
||||
|
||||
func (d *decoder) value(v reflect.Value) {
|
||||
switch v := v.(type) {
|
||||
case *reflect.ArrayValue:
|
||||
switch v.Kind() {
|
||||
case reflect.Array:
|
||||
l := v.Len()
|
||||
for i := 0; i < l; i++ {
|
||||
d.value(v.Elem(i))
|
||||
d.value(v.Index(i))
|
||||
}
|
||||
case *reflect.StructValue:
|
||||
case reflect.Struct:
|
||||
l := v.NumField()
|
||||
for i := 0; i < l; i++ {
|
||||
d.value(v.Field(i))
|
||||
}
|
||||
|
||||
case *reflect.SliceValue:
|
||||
case reflect.Slice:
|
||||
l := v.Len()
|
||||
for i := 0; i < l; i++ {
|
||||
d.value(v.Elem(i))
|
||||
d.value(v.Index(i))
|
||||
}
|
||||
|
||||
case *reflect.IntValue:
|
||||
switch v.Type().Kind() {
|
||||
case reflect.Int8:
|
||||
v.Set(int64(d.int8()))
|
||||
case reflect.Int16:
|
||||
v.Set(int64(d.int16()))
|
||||
case reflect.Int32:
|
||||
v.Set(int64(d.int32()))
|
||||
case reflect.Int64:
|
||||
v.Set(d.int64())
|
||||
}
|
||||
case reflect.Int8:
|
||||
v.SetInt(int64(d.int8()))
|
||||
case reflect.Int16:
|
||||
v.SetInt(int64(d.int16()))
|
||||
case reflect.Int32:
|
||||
v.SetInt(int64(d.int32()))
|
||||
case reflect.Int64:
|
||||
v.SetInt(d.int64())
|
||||
|
||||
case *reflect.UintValue:
|
||||
switch v.Type().Kind() {
|
||||
case reflect.Uint8:
|
||||
v.Set(uint64(d.uint8()))
|
||||
case reflect.Uint16:
|
||||
v.Set(uint64(d.uint16()))
|
||||
case reflect.Uint32:
|
||||
v.Set(uint64(d.uint32()))
|
||||
case reflect.Uint64:
|
||||
v.Set(d.uint64())
|
||||
}
|
||||
case reflect.Uint8:
|
||||
v.SetUint(uint64(d.uint8()))
|
||||
case reflect.Uint16:
|
||||
v.SetUint(uint64(d.uint16()))
|
||||
case reflect.Uint32:
|
||||
v.SetUint(uint64(d.uint32()))
|
||||
case reflect.Uint64:
|
||||
v.SetUint(d.uint64())
|
||||
|
||||
case *reflect.FloatValue:
|
||||
switch v.Type().Kind() {
|
||||
case reflect.Float32:
|
||||
v.Set(float64(math.Float32frombits(d.uint32())))
|
||||
case reflect.Float64:
|
||||
v.Set(math.Float64frombits(d.uint64()))
|
||||
}
|
||||
case reflect.Float32:
|
||||
v.SetFloat(float64(math.Float32frombits(d.uint32())))
|
||||
case reflect.Float64:
|
||||
v.SetFloat(math.Float64frombits(d.uint64()))
|
||||
|
||||
case *reflect.ComplexValue:
|
||||
switch v.Type().Kind() {
|
||||
case reflect.Complex64:
|
||||
v.Set(complex(
|
||||
float64(math.Float32frombits(d.uint32())),
|
||||
float64(math.Float32frombits(d.uint32())),
|
||||
))
|
||||
case reflect.Complex128:
|
||||
v.Set(complex(
|
||||
math.Float64frombits(d.uint64()),
|
||||
math.Float64frombits(d.uint64()),
|
||||
))
|
||||
}
|
||||
case reflect.Complex64:
|
||||
v.SetComplex(complex(
|
||||
float64(math.Float32frombits(d.uint32())),
|
||||
float64(math.Float32frombits(d.uint32())),
|
||||
))
|
||||
case reflect.Complex128:
|
||||
v.SetComplex(complex(
|
||||
math.Float64frombits(d.uint64()),
|
||||
math.Float64frombits(d.uint64()),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
func (e *encoder) value(v reflect.Value) {
|
||||
switch v := v.(type) {
|
||||
case *reflect.ArrayValue:
|
||||
switch v.Kind() {
|
||||
case reflect.Array:
|
||||
l := v.Len()
|
||||
for i := 0; i < l; i++ {
|
||||
e.value(v.Elem(i))
|
||||
e.value(v.Index(i))
|
||||
}
|
||||
case *reflect.StructValue:
|
||||
case reflect.Struct:
|
||||
l := v.NumField()
|
||||
for i := 0; i < l; i++ {
|
||||
e.value(v.Field(i))
|
||||
}
|
||||
case *reflect.SliceValue:
|
||||
case reflect.Slice:
|
||||
l := v.Len()
|
||||
for i := 0; i < l; i++ {
|
||||
e.value(v.Elem(i))
|
||||
e.value(v.Index(i))
|
||||
}
|
||||
|
||||
case *reflect.IntValue:
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
switch v.Type().Kind() {
|
||||
case reflect.Int8:
|
||||
e.int8(int8(v.Get()))
|
||||
e.int8(int8(v.Int()))
|
||||
case reflect.Int16:
|
||||
e.int16(int16(v.Get()))
|
||||
e.int16(int16(v.Int()))
|
||||
case reflect.Int32:
|
||||
e.int32(int32(v.Get()))
|
||||
e.int32(int32(v.Int()))
|
||||
case reflect.Int64:
|
||||
e.int64(v.Get())
|
||||
e.int64(v.Int())
|
||||
}
|
||||
|
||||
case *reflect.UintValue:
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
switch v.Type().Kind() {
|
||||
case reflect.Uint8:
|
||||
e.uint8(uint8(v.Get()))
|
||||
e.uint8(uint8(v.Uint()))
|
||||
case reflect.Uint16:
|
||||
e.uint16(uint16(v.Get()))
|
||||
e.uint16(uint16(v.Uint()))
|
||||
case reflect.Uint32:
|
||||
e.uint32(uint32(v.Get()))
|
||||
e.uint32(uint32(v.Uint()))
|
||||
case reflect.Uint64:
|
||||
e.uint64(v.Get())
|
||||
e.uint64(v.Uint())
|
||||
}
|
||||
|
||||
case *reflect.FloatValue:
|
||||
case reflect.Float32, reflect.Float64:
|
||||
switch v.Type().Kind() {
|
||||
case reflect.Float32:
|
||||
e.uint32(math.Float32bits(float32(v.Get())))
|
||||
e.uint32(math.Float32bits(float32(v.Float())))
|
||||
case reflect.Float64:
|
||||
e.uint64(math.Float64bits(v.Get()))
|
||||
e.uint64(math.Float64bits(v.Float()))
|
||||
}
|
||||
|
||||
case *reflect.ComplexValue:
|
||||
case reflect.Complex64, reflect.Complex128:
|
||||
switch v.Type().Kind() {
|
||||
case reflect.Complex64:
|
||||
x := v.Get()
|
||||
x := v.Complex()
|
||||
e.uint32(math.Float32bits(float32(real(x))))
|
||||
e.uint32(math.Float32bits(float32(imag(x))))
|
||||
case reflect.Complex128:
|
||||
x := v.Get()
|
||||
x := v.Complex()
|
||||
e.uint64(math.Float64bits(real(x)))
|
||||
e.uint64(math.Float64bits(imag(x)))
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ func TestWriteT(t *testing.T) {
|
||||
t.Errorf("WriteT: have nil, want non-nil")
|
||||
}
|
||||
|
||||
tv := reflect.Indirect(reflect.NewValue(ts)).(*reflect.StructValue)
|
||||
tv := reflect.Indirect(reflect.ValueOf(ts))
|
||||
for i, n := 0, tv.NumField(); i < n; i++ {
|
||||
err = Write(buf, BigEndian, tv.Field(i).Interface())
|
||||
if err == nil {
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This package implements hexadecimal encoding and decoding.
|
||||
// Package hex implements hexadecimal encoding and decoding.
|
||||
package hex
|
||||
|
||||
import (
|
||||
|
@ -2,7 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// The line package implements a Reader that reads lines delimited by '\n' or ' \r\n'.
|
||||
// Package line implements a Reader that reads lines delimited by '\n' or
|
||||
// ' \r\n'.
|
||||
package line
|
||||
|
||||
import (
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This package implements the PEM data encoding, which originated in Privacy
|
||||
// Package pem implements the PEM data encoding, which originated in Privacy
|
||||
// Enhanced Mail. The most common use of PEM encoding today is in TLS keys and
|
||||
// certificates. See RFC 1421.
|
||||
package pem
|
||||
|
@ -2,9 +2,9 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// The exec package runs external commands. It wraps os.StartProcess
|
||||
// to make it easier to remap stdin and stdout, connect I/O with pipes,
|
||||
// and do other adjustments.
|
||||
// Package exec runs external commands. It wraps os.StartProcess to make it
|
||||
// easier to remap stdin and stdout, connect I/O with pipes, and do other
|
||||
// adjustments.
|
||||
package exec
|
||||
|
||||
// BUG(r): This package should be made even easier to use or merged into os.
|
||||
|
@ -9,19 +9,14 @@ import (
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
"os"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func run(argv []string, stdin, stdout, stderr int) (p *Cmd, err os.Error) {
|
||||
if runtime.GOOS == "windows" {
|
||||
argv = append([]string{"cmd", "/c"}, argv...)
|
||||
}
|
||||
exe, err := LookPath(argv[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p, err = Run(exe, argv, nil, "", stdin, stdout, stderr)
|
||||
return p, err
|
||||
return Run(exe, argv, nil, "", stdin, stdout, stderr)
|
||||
}
|
||||
|
||||
func TestRunCat(t *testing.T) {
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/* The datafmt package implements syntax-directed, type-driven formatting
|
||||
/* Package datafmt implements syntax-directed, type-driven formatting
|
||||
of arbitrary data structures. Formatting a data structure consists of
|
||||
two phases: first, a parser reads a format specification and builds a
|
||||
"compiled" format. Then, the format can be applied repeatedly to
|
||||
@ -408,20 +408,20 @@ func (s *State) error(msg string) {
|
||||
//
|
||||
|
||||
func typename(typ reflect.Type) string {
|
||||
switch typ.(type) {
|
||||
case *reflect.ArrayType:
|
||||
switch typ.Kind() {
|
||||
case reflect.Array:
|
||||
return "array"
|
||||
case *reflect.SliceType:
|
||||
case reflect.Slice:
|
||||
return "array"
|
||||
case *reflect.ChanType:
|
||||
case reflect.Chan:
|
||||
return "chan"
|
||||
case *reflect.FuncType:
|
||||
case reflect.Func:
|
||||
return "func"
|
||||
case *reflect.InterfaceType:
|
||||
case reflect.Interface:
|
||||
return "interface"
|
||||
case *reflect.MapType:
|
||||
case reflect.Map:
|
||||
return "map"
|
||||
case *reflect.PtrType:
|
||||
case reflect.Ptr:
|
||||
return "ptr"
|
||||
}
|
||||
return typ.String()
|
||||
@ -519,38 +519,38 @@ func (s *State) eval(fexpr expr, value reflect.Value, index int) bool {
|
||||
|
||||
case "*":
|
||||
// indirection: operation is type-specific
|
||||
switch v := value.(type) {
|
||||
case *reflect.ArrayValue:
|
||||
switch v := value; v.Kind() {
|
||||
case reflect.Array:
|
||||
if v.Len() <= index {
|
||||
return false
|
||||
}
|
||||
value = v.Elem(index)
|
||||
value = v.Index(index)
|
||||
|
||||
case *reflect.SliceValue:
|
||||
case reflect.Slice:
|
||||
if v.IsNil() || v.Len() <= index {
|
||||
return false
|
||||
}
|
||||
value = v.Elem(index)
|
||||
value = v.Index(index)
|
||||
|
||||
case *reflect.MapValue:
|
||||
case reflect.Map:
|
||||
s.error("reflection support for maps incomplete")
|
||||
|
||||
case *reflect.PtrValue:
|
||||
case reflect.Ptr:
|
||||
if v.IsNil() {
|
||||
return false
|
||||
}
|
||||
value = v.Elem()
|
||||
|
||||
case *reflect.InterfaceValue:
|
||||
case reflect.Interface:
|
||||
if v.IsNil() {
|
||||
return false
|
||||
}
|
||||
value = v.Elem()
|
||||
|
||||
case *reflect.ChanValue:
|
||||
case reflect.Chan:
|
||||
s.error("reflection support for chans incomplete")
|
||||
|
||||
case *reflect.FuncValue:
|
||||
case reflect.Func:
|
||||
s.error("reflection support for funcs incomplete")
|
||||
|
||||
default:
|
||||
@ -560,9 +560,9 @@ func (s *State) eval(fexpr expr, value reflect.Value, index int) bool {
|
||||
default:
|
||||
// value is value of named field
|
||||
var field reflect.Value
|
||||
if sval, ok := value.(*reflect.StructValue); ok {
|
||||
if sval := value; sval.Kind() == reflect.Struct {
|
||||
field = sval.FieldByName(t.fieldName)
|
||||
if field == nil {
|
||||
if !field.IsValid() {
|
||||
// TODO consider just returning false in this case
|
||||
s.error(fmt.Sprintf("error: no field `%s` in `%s`", t.fieldName, value.Type()))
|
||||
}
|
||||
@ -671,8 +671,8 @@ func (f Format) Eval(env Environment, args ...interface{}) ([]byte, os.Error) {
|
||||
|
||||
go func() {
|
||||
for _, v := range args {
|
||||
fld := reflect.NewValue(v)
|
||||
if fld == nil {
|
||||
fld := reflect.ValueOf(v)
|
||||
if !fld.IsValid() {
|
||||
errors <- os.NewError("nil argument")
|
||||
return
|
||||
}
|
||||
|
@ -8,7 +8,10 @@
|
||||
// and the X Render extension.
|
||||
package draw
|
||||
|
||||
import "image"
|
||||
import (
|
||||
"image"
|
||||
"image/ycbcr"
|
||||
)
|
||||
|
||||
// m is the maximum color value returned by image.Color.RGBA.
|
||||
const m = 1<<16 - 1
|
||||
@ -65,29 +68,42 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
|
||||
if dst0, ok := dst.(*image.RGBA); ok {
|
||||
if op == Over {
|
||||
if mask == nil {
|
||||
if src0, ok := src.(*image.ColorImage); ok {
|
||||
switch src0 := src.(type) {
|
||||
case *image.ColorImage:
|
||||
drawFillOver(dst0, r, src0)
|
||||
return
|
||||
}
|
||||
if src0, ok := src.(*image.RGBA); ok {
|
||||
case *image.RGBA:
|
||||
drawCopyOver(dst0, r, src0, sp)
|
||||
return
|
||||
case *image.NRGBA:
|
||||
drawNRGBAOver(dst0, r, src0, sp)
|
||||
return
|
||||
case *ycbcr.YCbCr:
|
||||
drawYCbCr(dst0, r, src0, sp)
|
||||
return
|
||||
}
|
||||
} else if mask0, ok := mask.(*image.Alpha); ok {
|
||||
if src0, ok := src.(*image.ColorImage); ok {
|
||||
switch src0 := src.(type) {
|
||||
case *image.ColorImage:
|
||||
drawGlyphOver(dst0, r, src0, mask0, mp)
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if mask == nil {
|
||||
if src0, ok := src.(*image.ColorImage); ok {
|
||||
switch src0 := src.(type) {
|
||||
case *image.ColorImage:
|
||||
drawFillSrc(dst0, r, src0)
|
||||
return
|
||||
}
|
||||
if src0, ok := src.(*image.RGBA); ok {
|
||||
case *image.RGBA:
|
||||
drawCopySrc(dst0, r, src0, sp)
|
||||
return
|
||||
case *image.NRGBA:
|
||||
drawNRGBASrc(dst0, r, src0, sp)
|
||||
return
|
||||
case *ycbcr.YCbCr:
|
||||
drawYCbCr(dst0, r, src0, sp)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -224,6 +240,36 @@ func drawCopyOver(dst *image.RGBA, r image.Rectangle, src *image.RGBA, sp image.
|
||||
}
|
||||
}
|
||||
|
||||
func drawNRGBAOver(dst *image.RGBA, r image.Rectangle, src *image.NRGBA, sp image.Point) {
|
||||
for y, sy := r.Min.Y, sp.Y; y != r.Max.Y; y, sy = y+1, sy+1 {
|
||||
dpix := dst.Pix[y*dst.Stride : (y+1)*dst.Stride]
|
||||
spix := src.Pix[sy*src.Stride : (sy+1)*src.Stride]
|
||||
for x, sx := r.Min.X, sp.X; x != r.Max.X; x, sx = x+1, sx+1 {
|
||||
// Convert from non-premultiplied color to pre-multiplied color.
|
||||
// The order of operations here is to match the NRGBAColor.RGBA
|
||||
// method in image/color.go.
|
||||
snrgba := spix[sx]
|
||||
sa := uint32(snrgba.A)
|
||||
sr := uint32(snrgba.R) * 0x101 * sa / 0xff
|
||||
sg := uint32(snrgba.G) * 0x101 * sa / 0xff
|
||||
sb := uint32(snrgba.B) * 0x101 * sa / 0xff
|
||||
sa *= 0x101
|
||||
|
||||
rgba := dpix[x]
|
||||
dr := uint32(rgba.R)
|
||||
dg := uint32(rgba.G)
|
||||
db := uint32(rgba.B)
|
||||
da := uint32(rgba.A)
|
||||
a := (m - sa) * 0x101
|
||||
dr = (dr*a + sr*m) / m
|
||||
dg = (dg*a + sg*m) / m
|
||||
db = (db*a + sb*m) / m
|
||||
da = (da*a + sa*m) / m
|
||||
dpix[x] = image.RGBAColor{uint8(dr >> 8), uint8(dg >> 8), uint8(db >> 8), uint8(da >> 8)}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func drawGlyphOver(dst *image.RGBA, r image.Rectangle, src *image.ColorImage, mask *image.Alpha, mp image.Point) {
|
||||
x0, x1 := r.Min.X, r.Max.X
|
||||
y0, y1 := r.Min.Y, r.Max.Y
|
||||
@ -311,6 +357,73 @@ func drawCopySrc(dst *image.RGBA, r image.Rectangle, src *image.RGBA, sp image.P
|
||||
}
|
||||
}
|
||||
|
||||
func drawNRGBASrc(dst *image.RGBA, r image.Rectangle, src *image.NRGBA, sp image.Point) {
|
||||
for y, sy := r.Min.Y, sp.Y; y != r.Max.Y; y, sy = y+1, sy+1 {
|
||||
dpix := dst.Pix[y*dst.Stride : (y+1)*dst.Stride]
|
||||
spix := src.Pix[sy*src.Stride : (sy+1)*src.Stride]
|
||||
for x, sx := r.Min.X, sp.X; x != r.Max.X; x, sx = x+1, sx+1 {
|
||||
// Convert from non-premultiplied color to pre-multiplied color.
|
||||
// The order of operations here is to match the NRGBAColor.RGBA
|
||||
// method in image/color.go.
|
||||
snrgba := spix[sx]
|
||||
sa := uint32(snrgba.A)
|
||||
sr := uint32(snrgba.R) * 0x101 * sa / 0xff
|
||||
sg := uint32(snrgba.G) * 0x101 * sa / 0xff
|
||||
sb := uint32(snrgba.B) * 0x101 * sa / 0xff
|
||||
sa *= 0x101
|
||||
|
||||
dpix[x] = image.RGBAColor{uint8(sr >> 8), uint8(sg >> 8), uint8(sb >> 8), uint8(sa >> 8)}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func drawYCbCr(dst *image.RGBA, r image.Rectangle, src *ycbcr.YCbCr, sp image.Point) {
|
||||
// A YCbCr image is always fully opaque, and so if the mask is implicitly nil
|
||||
// (i.e. fully opaque) then the op is effectively always Src.
|
||||
var (
|
||||
yy, cb, cr uint8
|
||||
rr, gg, bb uint8
|
||||
)
|
||||
switch src.SubsampleRatio {
|
||||
case ycbcr.SubsampleRatio422:
|
||||
for y, sy := r.Min.Y, sp.Y; y != r.Max.Y; y, sy = y+1, sy+1 {
|
||||
dpix := dst.Pix[y*dst.Stride : (y+1)*dst.Stride]
|
||||
for x, sx := r.Min.X, sp.X; x != r.Max.X; x, sx = x+1, sx+1 {
|
||||
i := sx / 2
|
||||
yy = src.Y[sy*src.YStride+sx]
|
||||
cb = src.Cb[sy*src.CStride+i]
|
||||
cr = src.Cr[sy*src.CStride+i]
|
||||
rr, gg, bb = ycbcr.YCbCrToRGB(yy, cb, cr)
|
||||
dpix[x] = image.RGBAColor{rr, gg, bb, 255}
|
||||
}
|
||||
}
|
||||
case ycbcr.SubsampleRatio420:
|
||||
for y, sy := r.Min.Y, sp.Y; y != r.Max.Y; y, sy = y+1, sy+1 {
|
||||
dpix := dst.Pix[y*dst.Stride : (y+1)*dst.Stride]
|
||||
for x, sx := r.Min.X, sp.X; x != r.Max.X; x, sx = x+1, sx+1 {
|
||||
i, j := sx/2, sy/2
|
||||
yy = src.Y[sy*src.YStride+sx]
|
||||
cb = src.Cb[j*src.CStride+i]
|
||||
cr = src.Cr[j*src.CStride+i]
|
||||
rr, gg, bb = ycbcr.YCbCrToRGB(yy, cb, cr)
|
||||
dpix[x] = image.RGBAColor{rr, gg, bb, 255}
|
||||
}
|
||||
}
|
||||
default:
|
||||
// Default to 4:4:4 subsampling.
|
||||
for y, sy := r.Min.Y, sp.Y; y != r.Max.Y; y, sy = y+1, sy+1 {
|
||||
dpix := dst.Pix[y*dst.Stride : (y+1)*dst.Stride]
|
||||
for x, sx := r.Min.X, sp.X; x != r.Max.X; x, sx = x+1, sx+1 {
|
||||
yy = src.Y[sy*src.YStride+sx]
|
||||
cb = src.Cb[sy*src.CStride+sx]
|
||||
cr = src.Cr[sy*src.CStride+sx]
|
||||
rr, gg, bb = ycbcr.YCbCrToRGB(yy, cb, cr)
|
||||
dpix[x] = image.RGBAColor{rr, gg, bb, 255}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func drawRGBA(dst *image.RGBA, r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, op Op) {
|
||||
x0, x1, dx := r.Min.X, r.Max.X, 1
|
||||
y0, y1, dy := r.Min.Y, r.Max.Y, 1
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user