mirror of
https://github.com/golang/go.git
synced 2026-02-06 19:05:05 +03:00
Compare commits
31 Commits
dev.boring
...
dev.typeal
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a5ef1501d | ||
|
|
1ba29926f3 | ||
|
|
a4c18f063b | ||
|
|
0954fdd51e | ||
|
|
3b4fc5d1c6 | ||
|
|
f8b4123613 | ||
|
|
9ecc3ee252 | ||
|
|
49b7af8a30 | ||
|
|
9bbb07ddec | ||
|
|
43c7094386 | ||
|
|
9657e0b077 | ||
|
|
de2e5459ae | ||
|
|
9259f3073a | ||
|
|
5d92916770 | ||
|
|
a7c884efc1 | ||
|
|
5802cfd900 | ||
|
|
d7cabd40dd | ||
|
|
cc2dcce3d7 | ||
|
|
5c160b28ba | ||
|
|
b2386dffa1 | ||
|
|
ac8421f9a5 | ||
|
|
f011e0c6c3 | ||
|
|
49de5f0351 | ||
|
|
5ceec42dc0 | ||
|
|
aa1f0681bc | ||
|
|
c80748e389 | ||
|
|
80d8b69e95 | ||
|
|
a917097b5e | ||
|
|
3e11940437 | ||
|
|
e0a05c274a | ||
|
|
2e5116bd99 |
@@ -1,18 +0,0 @@
|
||||
# dev.boringcrypto branch
|
||||
|
||||
We have been working inside Google on a fork of Go that uses
|
||||
BoringCrypto (the core of [BoringSSL](https://boringssl.googlesource.com/boringssl/)) for various crypto primitives, in
|
||||
furtherance of some [work related to FIPS 140-2](http://csrc.nist.gov/groups/STM/cmvp/documents/140-1/140sp/140sp2964.pdf). We have heard that
|
||||
some external users of Go would be interested in this code as well, so
|
||||
I intend to create a new branch dev.boringcrypto that will hold
|
||||
patches to make Go use BoringCrypto.
|
||||
|
||||
Unlike typical dev branches, we do not intend any eventual merge of
|
||||
this code into the master branch. Instead we intend to maintain in
|
||||
that branch the latest release plus BoringCrypto patches. In this
|
||||
sense it is a bit like dev.typealias holding go1.8+type alias patches.
|
||||
|
||||
To be clear, we are not making any statements or representations about
|
||||
the suitability of this code in relation to the FIPS 140-2 standard.
|
||||
Interested users will have to evaluate for themselves whether the code
|
||||
is useful for their own purposes.
|
||||
@@ -57,7 +57,6 @@ pkg crypto/x509, const SHA384WithRSAPSS SignatureAlgorithm
|
||||
pkg crypto/x509, const SHA512WithRSAPSS = 15
|
||||
pkg crypto/x509, const SHA512WithRSAPSS SignatureAlgorithm
|
||||
pkg crypto/x509, type UnknownAuthorityError struct, Cert *Certificate
|
||||
pkg crypto/x509, type VerifyOptions struct, IsBoring func(*Certificate) bool
|
||||
pkg database/sql, const LevelDefault = 0
|
||||
pkg database/sql, const LevelDefault IsolationLevel
|
||||
pkg database/sql, const LevelLinearizable = 7
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<!--{
|
||||
"Title": "The Go Programming Language Specification",
|
||||
"Subtitle": "Version of November 18, 2016",
|
||||
"Subtitle": "Version of January 31, 2017",
|
||||
"Path": "/ref/spec"
|
||||
}-->
|
||||
|
||||
@@ -738,7 +738,7 @@ The method set of any other type <code>T</code> consists of all
|
||||
The method set of the corresponding <a href="#Pointer_types">pointer type</a> <code>*T</code>
|
||||
is the set of all methods declared with receiver <code>*T</code> or <code>T</code>
|
||||
(that is, it also contains the method set of <code>T</code>).
|
||||
Further rules apply to structs containing anonymous fields, as described
|
||||
Further rules apply to structs containing embedded fields, as described
|
||||
in the section on <a href="#Struct_types">struct types</a>.
|
||||
Any other type has an empty method set.
|
||||
In a method set, each method must have a
|
||||
@@ -947,16 +947,16 @@ Moreover, the inner slices must be initialized individually.
|
||||
<p>
|
||||
A struct is a sequence of named elements, called fields, each of which has a
|
||||
name and a type. Field names may be specified explicitly (IdentifierList) or
|
||||
implicitly (AnonymousField).
|
||||
implicitly (EmbeddedField).
|
||||
Within a struct, non-<a href="#Blank_identifier">blank</a> field names must
|
||||
be <a href="#Uniqueness_of_identifiers">unique</a>.
|
||||
</p>
|
||||
|
||||
<pre class="ebnf">
|
||||
StructType = "struct" "{" { FieldDecl ";" } "}" .
|
||||
FieldDecl = (IdentifierList Type | AnonymousField) [ Tag ] .
|
||||
AnonymousField = [ "*" ] TypeName .
|
||||
Tag = string_lit .
|
||||
StructType = "struct" "{" { FieldDecl ";" } "}" .
|
||||
FieldDecl = (IdentifierList Type | EmbeddedField) [ Tag ] .
|
||||
EmbeddedField = [ "*" ] TypeName .
|
||||
Tag = string_lit .
|
||||
</pre>
|
||||
|
||||
<pre>
|
||||
@@ -974,16 +974,15 @@ struct {
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
A field declared with a type but no explicit field name is an <i>anonymous field</i>,
|
||||
also called an <i>embedded</i> field or an embedding of the type in the struct.
|
||||
An embedded type must be specified as
|
||||
A field declared with a type but no explicit field name is called an <i>embedded field</i>.
|
||||
An embedded field must be specified as
|
||||
a type name <code>T</code> or as a pointer to a non-interface type name <code>*T</code>,
|
||||
and <code>T</code> itself may not be
|
||||
a pointer type. The unqualified type name acts as the field name.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
// A struct with four anonymous fields of type T1, *T2, P.T3 and *P.T4
|
||||
// A struct with four embedded fields of types T1, *T2, P.T3 and *P.T4
|
||||
struct {
|
||||
T1 // field name is T1
|
||||
*T2 // field name is T2
|
||||
@@ -1000,15 +999,15 @@ in a struct type:
|
||||
|
||||
<pre>
|
||||
struct {
|
||||
T // conflicts with anonymous field *T and *P.T
|
||||
*T // conflicts with anonymous field T and *P.T
|
||||
*P.T // conflicts with anonymous field T and *T
|
||||
T // conflicts with embedded field *T and *P.T
|
||||
*T // conflicts with embedded field T and *P.T
|
||||
*P.T // conflicts with embedded field T and *T
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
A field or <a href="#Method_declarations">method</a> <code>f</code> of an
|
||||
anonymous field in a struct <code>x</code> is called <i>promoted</i> if
|
||||
embedded field in a struct <code>x</code> is called <i>promoted</i> if
|
||||
<code>x.f</code> is a legal <a href="#Selectors">selector</a> that denotes
|
||||
that field or method <code>f</code>.
|
||||
</p>
|
||||
@@ -1025,7 +1024,7 @@ promoted methods are included in the method set of the struct as follows:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
If <code>S</code> contains an anonymous field <code>T</code>,
|
||||
If <code>S</code> contains an embedded field <code>T</code>,
|
||||
the <a href="#Method_sets">method sets</a> of <code>S</code>
|
||||
and <code>*S</code> both include promoted methods with receiver
|
||||
<code>T</code>. The method set of <code>*S</code> also
|
||||
@@ -1033,7 +1032,7 @@ promoted methods are included in the method set of the struct as follows:
|
||||
</li>
|
||||
|
||||
<li>
|
||||
If <code>S</code> contains an anonymous field <code>*T</code>,
|
||||
If <code>S</code> contains an embedded field <code>*T</code>,
|
||||
the method sets of <code>S</code> and <code>*S</code> both
|
||||
include promoted methods with receiver <code>T</code> or
|
||||
<code>*T</code>.
|
||||
@@ -1434,8 +1433,8 @@ literal structure and corresponding components have identical types. In detail:
|
||||
<li>Two struct types are identical if they have the same sequence of fields,
|
||||
and if corresponding fields have the same names, and identical types,
|
||||
and identical tags.
|
||||
Two anonymous fields are considered to have the same name. Lower-case field
|
||||
names from different packages are always different.</li>
|
||||
<a href="#Exported_identifiers">Non-exported</a> field names from different
|
||||
packages are always different.</li>
|
||||
|
||||
<li>Two pointer types are identical if they have identical base types.</li>
|
||||
|
||||
@@ -1445,8 +1444,9 @@ literal structure and corresponding components have identical types. In detail:
|
||||
Parameter and result names are not required to match.</li>
|
||||
|
||||
<li>Two interface types are identical if they have the same set of methods
|
||||
with the same names and identical function types. Lower-case method names from
|
||||
different packages are always different. The order of the methods is irrelevant.</li>
|
||||
with the same names and identical function types.
|
||||
<a href="#Exported_identifiers">Non-exported</a> method names from different
|
||||
packages are always different. The order of the methods is irrelevant.</li>
|
||||
|
||||
<li>Two map types are identical if they have identical key and value types.</li>
|
||||
|
||||
@@ -1891,7 +1891,7 @@ type NewMutex Mutex
|
||||
type PtrMutex *Mutex
|
||||
|
||||
// The method set of *PrintableMutex contains the methods
|
||||
// Lock and Unlock bound to its anonymous field Mutex.
|
||||
// Lock and Unlock bound to its embedded field Mutex.
|
||||
type PrintableMutex struct {
|
||||
Mutex
|
||||
}
|
||||
@@ -2492,13 +2492,13 @@ If <code>x</code> is a package name, see the section on
|
||||
A selector <code>f</code> may denote a field or method <code>f</code> of
|
||||
a type <code>T</code>, or it may refer
|
||||
to a field or method <code>f</code> of a nested
|
||||
<a href="#Struct_types">anonymous field</a> of <code>T</code>.
|
||||
The number of anonymous fields traversed
|
||||
<a href="#Struct_types">embedded field</a> of <code>T</code>.
|
||||
The number of embedded fields traversed
|
||||
to reach <code>f</code> is called its <i>depth</i> in <code>T</code>.
|
||||
The depth of a field or method <code>f</code>
|
||||
declared in <code>T</code> is zero.
|
||||
The depth of a field or method <code>f</code> declared in
|
||||
an anonymous field <code>A</code> in <code>T</code> is the
|
||||
an embedded field <code>A</code> in <code>T</code> is the
|
||||
depth of <code>f</code> in <code>A</code> plus one.
|
||||
</p>
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@ packaged Go distribution.
|
||||
<p>
|
||||
To build a bootstrap tool chain from source, use
|
||||
either the git branch <code>release-branch.go1.4</code> or
|
||||
<a href="https://storage.googleapis.com/golang/go1.4-bootstrap-20170531.tar.gz">go1.4-bootstrap-20170531.tar.gz</a>,
|
||||
<a href="https://storage.googleapis.com/golang/go1.4-bootstrap-20161024.tar.gz">go1.4-bootstrap-20161024.tar.gz</a>,
|
||||
which contains the Go 1.4 source code plus accumulated fixes
|
||||
to keep the tools running on newer operating systems.
|
||||
(Go 1.4 was the last distribution in which the tool chain was written in C.)
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
4
|
||||
@@ -74,7 +74,13 @@ func widstruct(errtype *Type, t *Type, o int64, flag int) int64 {
|
||||
lastzero = o
|
||||
}
|
||||
o += w
|
||||
if o >= Thearch.MAXWIDTH {
|
||||
maxwidth := Thearch.MAXWIDTH
|
||||
// On 32-bit systems, reflect tables impose an additional constraint
|
||||
// that each field start offset must fit in 31 bits.
|
||||
if maxwidth < 1<<32 {
|
||||
maxwidth = 1<<31 - 1
|
||||
}
|
||||
if o >= maxwidth {
|
||||
yyerror("type %L too large", errtype)
|
||||
o = 8 // small but nonzero
|
||||
}
|
||||
|
||||
@@ -140,11 +140,12 @@ const debugFormat = false // default: false
|
||||
const forceObjFileStability = true
|
||||
|
||||
// Current export format version. Increase with each format change.
|
||||
// 3: added aliasTag and export of aliases
|
||||
// 2: removed unused bool in ODCL export
|
||||
// 4: type name objects support type aliases, uses aliasTag
|
||||
// 3: Go1.8 encoding (same as version 2, aliasTag defined but never used)
|
||||
// 2: removed unused bool in ODCL export (compiler only)
|
||||
// 1: header format change (more regular), export package for _ struct fields
|
||||
// 0: Go1.7 encoding
|
||||
const exportVersion = 3
|
||||
const exportVersion = 4
|
||||
|
||||
// exportInlined enables the export of inlined function bodies and related
|
||||
// dependencies. The compiler should work w/o any loss of functionality with
|
||||
@@ -351,8 +352,8 @@ func export(out *bufio.Writer, trace bool) int {
|
||||
p.tracef("\n")
|
||||
}
|
||||
|
||||
if sym.Flags&SymAlias != 0 {
|
||||
Fatalf("exporter: unexpected alias %v in inlined function body", sym)
|
||||
if sym.isAlias() {
|
||||
Fatalf("exporter: unexpected type alias %v in inlined function body", sym)
|
||||
}
|
||||
|
||||
p.obj(sym)
|
||||
@@ -446,30 +447,6 @@ func unidealType(typ *Type, val Val) *Type {
|
||||
}
|
||||
|
||||
func (p *exporter) obj(sym *Sym) {
|
||||
if sym.Flags&SymAlias != 0 {
|
||||
p.tag(aliasTag)
|
||||
p.pos(nil) // TODO(gri) fix position information
|
||||
// Aliases can only be exported from the package that
|
||||
// declares them (aliases to aliases are resolved to the
|
||||
// original object, and so are uses of aliases in inlined
|
||||
// exported function bodies). Thus, we only need the alias
|
||||
// name without package qualification.
|
||||
if sym.Pkg != localpkg {
|
||||
Fatalf("exporter: export of non-local alias: %v", sym)
|
||||
}
|
||||
p.string(sym.Name)
|
||||
orig := sym.Def.Sym
|
||||
if orig.Flags&SymAlias != 0 {
|
||||
Fatalf("exporter: original object %v marked as alias", sym)
|
||||
}
|
||||
p.qualifiedName(orig)
|
||||
return
|
||||
}
|
||||
|
||||
if sym != sym.Def.Sym {
|
||||
Fatalf("exporter: exported object %v is not original %v", sym, sym.Def.Sym)
|
||||
}
|
||||
|
||||
// Exported objects may be from different packages because they
|
||||
// may be re-exported via an exported alias or as dependencies in
|
||||
// exported inlined function bodies. Thus, exported object names
|
||||
@@ -509,7 +486,13 @@ func (p *exporter) obj(sym *Sym) {
|
||||
Fatalf("exporter: export of incomplete type %v", sym)
|
||||
}
|
||||
|
||||
p.tag(typeTag)
|
||||
if sym.isAlias() {
|
||||
p.tag(aliasTag)
|
||||
p.pos(n)
|
||||
p.qualifiedName(sym)
|
||||
} else {
|
||||
p.tag(typeTag)
|
||||
}
|
||||
p.typ(t)
|
||||
|
||||
case ONAME:
|
||||
@@ -868,19 +851,29 @@ func (p *exporter) methodList(t *Type) {
|
||||
|
||||
func (p *exporter) method(m *Field) {
|
||||
p.pos(m.Nname)
|
||||
p.fieldName(m)
|
||||
p.methodName(m.Sym)
|
||||
p.paramList(m.Type.Params(), false)
|
||||
p.paramList(m.Type.Results(), false)
|
||||
}
|
||||
|
||||
// fieldName is like qualifiedName but it doesn't record the package for exported names.
|
||||
func (p *exporter) fieldName(t *Field) {
|
||||
name := t.Sym.Name
|
||||
if t.Embedded != 0 {
|
||||
name = "" // anonymous field
|
||||
if bname := basetypeName(t.Type); bname != "" && !exportname(bname) {
|
||||
// anonymous field with unexported base type name
|
||||
name = "?" // unexported name to force export of package
|
||||
// anonymous field - we distinguish between 3 cases:
|
||||
// 1) field name matches base type name and is exported
|
||||
// 2) field name matches base type name and is not exported
|
||||
// 3) field name doesn't match base type name (alias name)
|
||||
bname := basetypeName(t.Type)
|
||||
if name == bname {
|
||||
if exportname(name) {
|
||||
name = "" // 1) we don't need to know the field name or package
|
||||
} else {
|
||||
name = "?" // 2) use unexported name "?" to force package export
|
||||
}
|
||||
} else {
|
||||
// 3) indicate alias and export name as is
|
||||
// (this requires an extra "@" but this is a rare case)
|
||||
p.string("@")
|
||||
}
|
||||
}
|
||||
p.string(name)
|
||||
@@ -889,16 +882,23 @@ func (p *exporter) fieldName(t *Field) {
|
||||
}
|
||||
}
|
||||
|
||||
// methodName is like qualifiedName but it doesn't record the package for exported names.
|
||||
func (p *exporter) methodName(sym *Sym) {
|
||||
p.string(sym.Name)
|
||||
if !exportname(sym.Name) {
|
||||
p.pkg(sym.Pkg)
|
||||
}
|
||||
}
|
||||
|
||||
func basetypeName(t *Type) string {
|
||||
s := t.Sym
|
||||
if s == nil && t.IsPtr() {
|
||||
s = t.Elem().Sym // deref
|
||||
}
|
||||
// s should exist, but be conservative
|
||||
if s != nil {
|
||||
return s.Name
|
||||
}
|
||||
return ""
|
||||
return "" // unnamed type
|
||||
}
|
||||
|
||||
func (p *exporter) paramList(params *Type, numbered bool) {
|
||||
@@ -1797,7 +1797,7 @@ const (
|
||||
nilTag
|
||||
unknownTag // not used by gc (only appears in packages with errors)
|
||||
|
||||
// Aliases
|
||||
// Type aliases
|
||||
aliasTag
|
||||
)
|
||||
|
||||
@@ -1835,7 +1835,7 @@ var tagString = [...]string{
|
||||
-nilTag: "nil",
|
||||
-unknownTag: "unknown",
|
||||
|
||||
// Aliases
|
||||
// Type aliases
|
||||
-aliasTag: "alias",
|
||||
}
|
||||
|
||||
@@ -1889,7 +1889,7 @@ func predeclared() []*Type {
|
||||
Types[TCOMPLEX128],
|
||||
Types[TSTRING],
|
||||
|
||||
// aliases
|
||||
// basic type aliases
|
||||
bytetype,
|
||||
runetype,
|
||||
|
||||
|
||||
@@ -86,10 +86,10 @@ func Import(in *bufio.Reader) {
|
||||
|
||||
// read version specific flags - extend as necessary
|
||||
switch p.version {
|
||||
// case 4:
|
||||
// case 5:
|
||||
// ...
|
||||
// fallthrough
|
||||
case 3, 2, 1:
|
||||
case 4, 3, 2, 1:
|
||||
p.debugFormat = p.rawStringln(p.rawByte()) == "debug"
|
||||
p.trackAllTypes = p.bool()
|
||||
p.posInfoFormat = p.bool()
|
||||
@@ -317,6 +317,12 @@ func (p *importer) obj(tag int) {
|
||||
val := p.value(typ)
|
||||
importconst(sym, idealType(typ), nodlit(val))
|
||||
|
||||
case aliasTag:
|
||||
p.pos()
|
||||
sym := p.qualifiedName()
|
||||
typ := p.typ()
|
||||
importalias(sym, typ)
|
||||
|
||||
case typeTag:
|
||||
p.typ()
|
||||
|
||||
@@ -356,17 +362,6 @@ func (p *importer) obj(tag int) {
|
||||
}
|
||||
}
|
||||
|
||||
case aliasTag:
|
||||
p.pos()
|
||||
alias := importpkg.Lookup(p.string())
|
||||
orig := p.qualifiedName()
|
||||
|
||||
// Although the protocol allows the alias to precede the original,
|
||||
// this never happens in files produced by gc.
|
||||
alias.Flags |= SymAlias
|
||||
alias.Def = orig.Def
|
||||
importsym(alias, orig.Def.Op)
|
||||
|
||||
default:
|
||||
formatErrorf("unexpected object (tag = %d)", tag)
|
||||
}
|
||||
@@ -473,14 +468,7 @@ func (p *importer) typ() *Type {
|
||||
result := p.paramList()
|
||||
nointerface := p.bool()
|
||||
|
||||
base := recv[0].Type
|
||||
star := false
|
||||
if base.IsPtr() {
|
||||
base = base.Elem()
|
||||
star = true
|
||||
}
|
||||
|
||||
n := methodname0(sym, star, base.Sym)
|
||||
n := newfuncname(methodname(sym, recv[0].Type))
|
||||
n.Type = functypefield(recv[0], params, result)
|
||||
checkwidth(n.Type)
|
||||
addmethod(sym, n.Type, false, nointerface)
|
||||
@@ -583,19 +571,22 @@ func (p *importer) fieldList() (fields []*Field) {
|
||||
|
||||
func (p *importer) field() *Field {
|
||||
p.pos()
|
||||
sym := p.fieldName()
|
||||
sym, alias := p.fieldName()
|
||||
typ := p.typ()
|
||||
note := p.string()
|
||||
|
||||
f := newField()
|
||||
if sym.Name == "" {
|
||||
// anonymous field - typ must be T or *T and T must be a type name
|
||||
// anonymous field: typ must be T or *T and T must be a type name
|
||||
s := typ.Sym
|
||||
if s == nil && typ.IsPtr() {
|
||||
s = typ.Elem().Sym // deref
|
||||
}
|
||||
sym = sym.Pkg.Lookup(s.Name)
|
||||
f.Embedded = 1
|
||||
} else if alias {
|
||||
// anonymous field: we have an explicit name because it's a type alias
|
||||
f.Embedded = 1
|
||||
}
|
||||
|
||||
f.Sym = sym
|
||||
@@ -618,7 +609,7 @@ func (p *importer) methodList() (methods []*Field) {
|
||||
|
||||
func (p *importer) method() *Field {
|
||||
p.pos()
|
||||
sym := p.fieldName()
|
||||
sym := p.methodName()
|
||||
params := p.paramList()
|
||||
result := p.paramList()
|
||||
|
||||
@@ -629,18 +620,44 @@ func (p *importer) method() *Field {
|
||||
return f
|
||||
}
|
||||
|
||||
func (p *importer) fieldName() *Sym {
|
||||
func (p *importer) fieldName() (*Sym, bool) {
|
||||
name := p.string()
|
||||
if p.version == 0 && name == "_" {
|
||||
// version 0 didn't export a package for _ fields
|
||||
// version 0 didn't export a package for _ field names
|
||||
// but used the builtin package instead
|
||||
return builtinpkg.Lookup(name), false
|
||||
}
|
||||
pkg := localpkg
|
||||
alias := false
|
||||
switch name {
|
||||
case "":
|
||||
// 1) field name matches base type name and is exported: nothing to do
|
||||
case "?":
|
||||
// 2) field name matches base type name and is not exported: need package
|
||||
name = ""
|
||||
pkg = p.pkg()
|
||||
case "@":
|
||||
// 3) field name doesn't match base type name (alias name): need name and possibly package
|
||||
name = p.string()
|
||||
alias = true
|
||||
fallthrough
|
||||
default:
|
||||
if !exportname(name) {
|
||||
pkg = p.pkg()
|
||||
}
|
||||
}
|
||||
return pkg.Lookup(name), alias
|
||||
}
|
||||
|
||||
func (p *importer) methodName() *Sym {
|
||||
name := p.string()
|
||||
if p.version == 0 && name == "_" {
|
||||
// version 0 didn't export a package for _ method names
|
||||
// but used the builtin package instead
|
||||
return builtinpkg.Lookup(name)
|
||||
}
|
||||
pkg := localpkg
|
||||
if name != "" && !exportname(name) {
|
||||
if name == "?" {
|
||||
name = ""
|
||||
}
|
||||
if !exportname(name) {
|
||||
pkg = p.pkg()
|
||||
}
|
||||
return pkg.Lookup(name)
|
||||
|
||||
@@ -519,10 +519,6 @@ func funchdr(n *Node) {
|
||||
Fatalf("funchdr: dclcontext = %d", dclcontext)
|
||||
}
|
||||
|
||||
if Ctxt.Flag_dynlink && importpkg == nil && n.Func.Nname != nil {
|
||||
makefuncsym(n.Func.Nname.Sym)
|
||||
}
|
||||
|
||||
dclcontext = PAUTO
|
||||
funcstart(n)
|
||||
|
||||
@@ -695,10 +691,20 @@ func typedcl0(s *Sym) *Node {
|
||||
|
||||
// node n, which was returned by typedcl0
|
||||
// is being declared to have uncompiled type t.
|
||||
// return the ODCLTYPE node to use.
|
||||
func typedcl1(n *Node, t *Node, local bool) *Node {
|
||||
n.Name.Param.Ntype = t
|
||||
n.Local = local
|
||||
// returns the ODCLTYPE node to use.
|
||||
func typedcl1(n *Node, t *Node, pragma Pragma, alias bool) *Node {
|
||||
if pragma != 0 && alias {
|
||||
yyerror("cannot specify directive with type alias")
|
||||
pragma = 0
|
||||
}
|
||||
|
||||
n.Local = true
|
||||
|
||||
p := n.Name.Param
|
||||
p.Ntype = t
|
||||
p.Pragma = pragma
|
||||
p.Alias = alias
|
||||
|
||||
return nod(ODCLTYPE, n, nil)
|
||||
}
|
||||
|
||||
@@ -1153,19 +1159,19 @@ bad:
|
||||
return nil
|
||||
}
|
||||
|
||||
func methodname(n *Node, t *Node) *Node {
|
||||
// methodname is a misnomer because this now returns a Sym, rather
|
||||
// than an ONAME.
|
||||
// TODO(mdempsky): Reconcile with methodsym.
|
||||
func methodname(s *Sym, recv *Type) *Sym {
|
||||
star := false
|
||||
if t.Op == OIND {
|
||||
if recv.IsPtr() {
|
||||
star = true
|
||||
t = t.Left
|
||||
recv = recv.Elem()
|
||||
}
|
||||
|
||||
return methodname0(n.Sym, star, t.Sym)
|
||||
}
|
||||
|
||||
func methodname0(s *Sym, star bool, tsym *Sym) *Node {
|
||||
tsym := recv.Sym
|
||||
if tsym == nil || isblanksym(s) {
|
||||
return newfuncname(s)
|
||||
return s
|
||||
}
|
||||
|
||||
var p string
|
||||
@@ -1181,14 +1187,13 @@ func methodname0(s *Sym, star bool, tsym *Sym) *Node {
|
||||
s = Pkglookup(p, tsym.Pkg)
|
||||
}
|
||||
|
||||
return newfuncname(s)
|
||||
return s
|
||||
}
|
||||
|
||||
// Add a method, declared as a function.
|
||||
// - msym is the method symbol
|
||||
// - t is function type (with receiver)
|
||||
func addmethod(msym *Sym, t *Type, local, nointerface bool) {
|
||||
// get field sym
|
||||
if msym == nil {
|
||||
Fatalf("no method symbol")
|
||||
}
|
||||
@@ -1309,7 +1314,7 @@ func funcsym(s *Sym) *Sym {
|
||||
s1 := Pkglookup(s.Name+"·f", s.Pkg)
|
||||
if !Ctxt.Flag_dynlink && s1.Def == nil {
|
||||
s1.Def = newfuncname(s1)
|
||||
s1.Def.Func.Shortname = newname(s)
|
||||
s1.Def.Func.Shortname = s
|
||||
funcsyms = append(funcsyms, s1.Def)
|
||||
}
|
||||
s.Fsym = s1
|
||||
@@ -1326,8 +1331,11 @@ func makefuncsym(s *Sym) {
|
||||
return
|
||||
}
|
||||
s1 := funcsym(s)
|
||||
if s1.Def != nil {
|
||||
return
|
||||
}
|
||||
s1.Def = newfuncname(s1)
|
||||
s1.Def.Func.Shortname = newname(s)
|
||||
s1.Def.Func.Shortname = s
|
||||
funcsyms = append(funcsyms, s1.Def)
|
||||
}
|
||||
|
||||
|
||||
@@ -45,8 +45,8 @@ func exportsym(n *Node) {
|
||||
fmt.Printf("export symbol %v\n", n.Sym)
|
||||
}
|
||||
|
||||
// Ensure original object is on exportlist before aliases.
|
||||
if n.Sym.Flags&SymAlias != 0 {
|
||||
// Ensure original types are on exportlist before type aliases.
|
||||
if n.Sym.isAlias() {
|
||||
exportlist = append(exportlist, n.Sym.Def)
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ func autoexport(n *Node, ctxt Class) {
|
||||
if (ctxt != PEXTERN && ctxt != PFUNC) || dclcontext != PEXTERN {
|
||||
return
|
||||
}
|
||||
if n.Name.Param != nil && n.Name.Param.Ntype != nil && n.Name.Param.Ntype.Op == OTFUNC && n.Name.Param.Ntype.Left != nil { // method
|
||||
if n.Type != nil && n.Type.IsKind(TFUNC) && n.Type.Recv() != nil { // method
|
||||
return
|
||||
}
|
||||
|
||||
@@ -348,6 +348,27 @@ func importvar(s *Sym, t *Type) {
|
||||
}
|
||||
}
|
||||
|
||||
// importalias declares symbol s as an imported type alias with type t.
|
||||
func importalias(s *Sym, t *Type) {
|
||||
importsym(s, OTYPE)
|
||||
if s.Def != nil && s.Def.Op == OTYPE {
|
||||
if eqtype(t, s.Def.Type) {
|
||||
return
|
||||
}
|
||||
yyerror("inconsistent definition for type alias %v during import\n\t%v (in %q)\n\t%v (in %q)", s, s.Def.Type, s.Importdef.Path, t, importpkg.Path)
|
||||
}
|
||||
|
||||
n := newname(s)
|
||||
n.Op = OTYPE
|
||||
s.Importdef = importpkg
|
||||
n.Type = t
|
||||
declare(n, PEXTERN)
|
||||
|
||||
if Debug['E'] != 0 {
|
||||
fmt.Printf("import type %v = %L\n", s, t)
|
||||
}
|
||||
}
|
||||
|
||||
func dumpasmhdr() {
|
||||
b, err := bio.Create(asmhdr)
|
||||
if err != nil {
|
||||
|
||||
@@ -1077,6 +1077,7 @@ var opprec = []int{
|
||||
OSEND: 3,
|
||||
OANDAND: 2,
|
||||
OOROR: 1,
|
||||
|
||||
// Statements handled by stmtfmt
|
||||
OAS: -1,
|
||||
OAS2: -1,
|
||||
@@ -1104,7 +1105,8 @@ var opprec = []int{
|
||||
OSWITCH: -1,
|
||||
OXCASE: -1,
|
||||
OXFALL: -1,
|
||||
OEND: 0,
|
||||
|
||||
OEND: 0,
|
||||
}
|
||||
|
||||
func (n *Node) exprfmt(s fmt.State, prec int) {
|
||||
|
||||
@@ -63,9 +63,12 @@ const (
|
||||
SymSiggen
|
||||
SymAsm
|
||||
SymAlgGen
|
||||
SymAlias // alias, original is Sym.Def.Sym
|
||||
)
|
||||
|
||||
func (sym *Sym) isAlias() bool {
|
||||
return sym.Def != nil && sym.Def.Sym != sym
|
||||
}
|
||||
|
||||
// The Class of a variable/function describes the "storage class"
|
||||
// of a variable or function. During parsing, storage classes are
|
||||
// called declaration contexts.
|
||||
@@ -87,7 +90,7 @@ const (
|
||||
// of the compilers arrays.
|
||||
//
|
||||
// typedef struct
|
||||
// { // must not move anything
|
||||
// { // must not move anything
|
||||
// uchar array[8]; // pointer to data
|
||||
// uchar nel[4]; // number of elements
|
||||
// uchar cap[4]; // allocated number of elements
|
||||
@@ -104,7 +107,7 @@ var sizeof_Array int // runtime sizeof(Array)
|
||||
// of the compilers strings.
|
||||
//
|
||||
// typedef struct
|
||||
// { // must not move anything
|
||||
// { // must not move anything
|
||||
// uchar array[8]; // pointer to data
|
||||
// uchar nel[4]; // number of elements
|
||||
// } String;
|
||||
|
||||
@@ -340,13 +340,16 @@ func Main() {
|
||||
// Phase 1: const, type, and names and types of funcs.
|
||||
// This will gather all the information about types
|
||||
// and methods but doesn't depend on any of it.
|
||||
// We also defer type alias declarations until phase 2
|
||||
// to avoid cycles like #18640.
|
||||
defercheckwidth()
|
||||
|
||||
// Don't use range--typecheck can add closures to xtop.
|
||||
timings.Start("fe", "typecheck", "top1")
|
||||
for i := 0; i < len(xtop); i++ {
|
||||
if xtop[i].Op != ODCL && xtop[i].Op != OAS && xtop[i].Op != OAS2 {
|
||||
xtop[i] = typecheck(xtop[i], Etop)
|
||||
n := xtop[i]
|
||||
if op := n.Op; op != ODCL && op != OAS && op != OAS2 && (op != ODCLTYPE || !n.Left.Name.Param.Alias) {
|
||||
xtop[i] = typecheck(n, Etop)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -356,8 +359,9 @@ func Main() {
|
||||
// Don't use range--typecheck can add closures to xtop.
|
||||
timings.Start("fe", "typecheck", "top2")
|
||||
for i := 0; i < len(xtop); i++ {
|
||||
if xtop[i].Op == ODCL || xtop[i].Op == OAS || xtop[i].Op == OAS2 {
|
||||
xtop[i] = typecheck(xtop[i], Etop)
|
||||
n := xtop[i]
|
||||
if op := n.Op; op == ODCL || op == OAS || op == OAS2 || op == ODCLTYPE && n.Left.Name.Param.Alias {
|
||||
xtop[i] = typecheck(n, Etop)
|
||||
}
|
||||
}
|
||||
resumecheckwidth()
|
||||
@@ -367,8 +371,9 @@ func Main() {
|
||||
timings.Start("fe", "typecheck", "func")
|
||||
var fcount int64
|
||||
for i := 0; i < len(xtop); i++ {
|
||||
if xtop[i].Op == ODCLFUNC || xtop[i].Op == OCLOSURE {
|
||||
Curfn = xtop[i]
|
||||
n := xtop[i]
|
||||
if op := n.Op; op == ODCLFUNC || op == OCLOSURE {
|
||||
Curfn = n
|
||||
decldepth = 1
|
||||
saveerrors()
|
||||
typecheckslice(Curfn.Nbody.Slice(), Etop)
|
||||
@@ -460,8 +465,9 @@ func Main() {
|
||||
timings.Start("be", "compilefuncs")
|
||||
fcount = 0
|
||||
for i := 0; i < len(xtop); i++ {
|
||||
if xtop[i].Op == ODCLFUNC {
|
||||
funccompile(xtop[i])
|
||||
n := xtop[i]
|
||||
if n.Op == ODCLFUNC {
|
||||
funccompile(n)
|
||||
fcount++
|
||||
}
|
||||
}
|
||||
@@ -924,7 +930,7 @@ func mkpackage(pkgname string) {
|
||||
continue
|
||||
}
|
||||
|
||||
if s.Def.Sym != s && s.Flags&SymAlias == 0 {
|
||||
if s.isAlias() {
|
||||
// throw away top-level name left over
|
||||
// from previous import . "x"
|
||||
if s.Def.Name != nil && s.Def.Name.Pack != nil && !s.Def.Name.Pack.Used && nsyntaxerrors == 0 {
|
||||
|
||||
@@ -154,11 +154,7 @@ func (p *noder) importDecl(imp *syntax.ImportDecl) {
|
||||
|
||||
func (p *noder) varDecl(decl *syntax.VarDecl) []*Node {
|
||||
names := p.declNames(decl.NameList)
|
||||
|
||||
var typ *Node
|
||||
if decl.Type != nil {
|
||||
typ = p.typeExpr(decl.Type)
|
||||
}
|
||||
typ := p.typeExprOrNil(decl.Type)
|
||||
|
||||
var exprs []*Node
|
||||
if decl.Values != nil {
|
||||
@@ -171,11 +167,7 @@ func (p *noder) varDecl(decl *syntax.VarDecl) []*Node {
|
||||
|
||||
func (p *noder) constDecl(decl *syntax.ConstDecl) []*Node {
|
||||
names := p.declNames(decl.NameList)
|
||||
|
||||
var typ *Node
|
||||
if decl.Type != nil {
|
||||
typ = p.typeExpr(decl.Type)
|
||||
}
|
||||
typ := p.typeExprOrNil(decl.Type)
|
||||
|
||||
var exprs []*Node
|
||||
if decl.Values != nil {
|
||||
@@ -187,14 +179,11 @@ func (p *noder) constDecl(decl *syntax.ConstDecl) []*Node {
|
||||
|
||||
func (p *noder) typeDecl(decl *syntax.TypeDecl) *Node {
|
||||
name := typedcl0(p.name(decl.Name))
|
||||
name.Name.Param.Pragma = Pragma(decl.Pragma)
|
||||
|
||||
var typ *Node
|
||||
if decl.Type != nil {
|
||||
typ = p.typeExpr(decl.Type)
|
||||
}
|
||||
// decl.Type may be nil but in that case we got a syntax error during parsing
|
||||
typ := p.typeExprOrNil(decl.Type)
|
||||
|
||||
return typedcl1(name, typ, true)
|
||||
return typedcl1(name, typ, Pragma(decl.Pragma), decl.Alias)
|
||||
}
|
||||
|
||||
func (p *noder) declNames(names []*syntax.Name) []*Node {
|
||||
@@ -259,19 +248,19 @@ func (p *noder) funcHeader(fun *syntax.FuncDecl) *Node {
|
||||
yyerror("func main must have no arguments and no return values")
|
||||
}
|
||||
}
|
||||
|
||||
f.Func.Nname = newfuncname(name)
|
||||
} else {
|
||||
// Receiver MethodName Signature
|
||||
|
||||
f.Func.Shortname = newfuncname(name)
|
||||
f.Func.Nname = methodname(f.Func.Shortname, t.Left.Right)
|
||||
f.Func.Shortname = name
|
||||
name = nblank.Sym // filled in by typecheckfunc
|
||||
}
|
||||
|
||||
f.Func.Nname = newfuncname(name)
|
||||
f.Func.Nname.Name.Defn = f
|
||||
f.Func.Nname.Name.Param.Ntype = t // TODO: check if nname already has an ntype
|
||||
|
||||
declare(f.Func.Nname, PFUNC)
|
||||
if fun.Recv == nil {
|
||||
declare(f.Func.Nname, PFUNC)
|
||||
}
|
||||
|
||||
funchdr(f)
|
||||
return f
|
||||
}
|
||||
@@ -467,6 +456,13 @@ func (p *noder) typeExpr(typ syntax.Expr) *Node {
|
||||
return p.expr(typ)
|
||||
}
|
||||
|
||||
func (p *noder) typeExprOrNil(typ syntax.Expr) *Node {
|
||||
if typ != nil {
|
||||
return p.expr(typ)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *noder) chanDir(dir syntax.ChanDir) ChanDir {
|
||||
switch dir {
|
||||
case 0:
|
||||
|
||||
@@ -213,7 +213,7 @@ func dumpglobls() {
|
||||
}
|
||||
|
||||
for _, n := range funcsyms {
|
||||
dsymptr(n.Sym, 0, n.Sym.Def.Func.Shortname.Sym, 0)
|
||||
dsymptr(n.Sym, 0, n.Sym.Def.Func.Shortname, 0)
|
||||
ggloblsym(n.Sym, int32(Widthptr), obj.DUPOK|obj.RODATA)
|
||||
}
|
||||
|
||||
|
||||
@@ -511,7 +511,7 @@ func isExportedField(ft *Field) (bool, *Pkg) {
|
||||
// dnameField dumps a reflect.name for a struct field.
|
||||
func dnameField(s *Sym, ot int, spkg *Pkg, ft *Field) int {
|
||||
var name string
|
||||
if ft.Sym != nil && ft.Embedded == 0 {
|
||||
if ft.Sym != nil {
|
||||
name = ft.Sym.Name
|
||||
}
|
||||
isExported, fpkg := isExportedField(ft)
|
||||
@@ -1312,32 +1312,9 @@ ok:
|
||||
// ../../../../runtime/type.go:/structType
|
||||
// for security, only the exported fields.
|
||||
case TSTRUCT:
|
||||
|
||||
// omitFieldForAwfulBoringCryptoKludge reports whether
|
||||
// the field t should be omitted from the reflect data.
|
||||
// In the crypto/... packages we omit an unexported field
|
||||
// named "boring", to keep from breaking client code that
|
||||
// expects rsa.PublicKey etc to have only public fields.
|
||||
// As the name suggests, this is an awful kludge, but it is
|
||||
// limited to the dev.boringcrypto branch and avoids
|
||||
// much more invasive effects elsewhere.
|
||||
omitFieldForAwfulBoringCryptoKludge := func(t *Field) bool {
|
||||
if t.Sym == nil || t.Sym.Name != "boring" || t.Sym.Pkg == nil {
|
||||
return false
|
||||
}
|
||||
path := t.Sym.Pkg.Path
|
||||
if t.Sym.Pkg == localpkg {
|
||||
path = myimportpath
|
||||
}
|
||||
return strings.HasPrefix(path, "crypto/")
|
||||
}
|
||||
|
||||
n := 0
|
||||
|
||||
for _, t1 := range t.Fields().Slice() {
|
||||
if omitFieldForAwfulBoringCryptoKludge(t1) {
|
||||
continue
|
||||
}
|
||||
dtypesym(t1.Type)
|
||||
n++
|
||||
}
|
||||
@@ -1365,13 +1342,17 @@ ok:
|
||||
ot = dextratype(s, ot, t, dataAdd)
|
||||
|
||||
for _, f := range t.Fields().Slice() {
|
||||
if omitFieldForAwfulBoringCryptoKludge(f) {
|
||||
continue
|
||||
}
|
||||
// ../../../../runtime/type.go:/structField
|
||||
ot = dnameField(s, ot, pkg, f)
|
||||
ot = dsymptr(s, ot, dtypesym(f.Type), 0)
|
||||
ot = duintptr(s, ot, uint64(f.Offset))
|
||||
offsetAnon := uint64(f.Offset) << 1
|
||||
if offsetAnon>>1 != uint64(f.Offset) {
|
||||
Fatalf("%v: bad field offset for %s", t, f.Sym.Name)
|
||||
}
|
||||
if f.Embedded != 0 {
|
||||
offsetAnon |= 1
|
||||
}
|
||||
ot = duintptr(s, ot, offsetAnon)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ type Node struct {
|
||||
// func
|
||||
Func *Func
|
||||
|
||||
// ONAME
|
||||
// ONAME, OTYPE, OPACK, OLABEL, some OLITERAL
|
||||
Name *Name
|
||||
|
||||
Sym *Sym // various
|
||||
@@ -59,8 +59,8 @@ type Node struct {
|
||||
Noescape bool // func arguments do not escape; TODO(rsc): move Noescape to Func struct (see CL 7360)
|
||||
Walkdef uint8 // tracks state during typecheckdef; 2 == loop detected
|
||||
Typecheck uint8 // tracks state during typechecking; 2 == loop detected
|
||||
Local bool
|
||||
IsStatic bool // whether this Node will be converted to purely static data
|
||||
Local bool // type created in this file (see also Type.Local); TODO(gri): move this into flags
|
||||
IsStatic bool // whether this Node will be converted to purely static data
|
||||
Initorder uint8
|
||||
Used bool // for variable/label declared and not used error
|
||||
Isddd bool // is the argument variadic
|
||||
@@ -180,14 +180,14 @@ func (n *Node) SetIota(x int64) {
|
||||
n.Xoffset = x
|
||||
}
|
||||
|
||||
// Name holds Node fields used only by named nodes (ONAME, OPACK, OLABEL, some OLITERAL).
|
||||
// Name holds Node fields used only by named nodes (ONAME, OTYPE, OPACK, OLABEL, some OLITERAL).
|
||||
type Name struct {
|
||||
Pack *Node // real package for import . names
|
||||
Pkg *Pkg // pkg for OPACK nodes
|
||||
Heapaddr *Node // temp holding heap address of param (could move to Param?)
|
||||
Defn *Node // initializing assignment
|
||||
Curfn *Node // function for local variables
|
||||
Param *Param // additional fields for ONAME
|
||||
Param *Param // additional fields for ONAME, OTYPE
|
||||
Decldepth int32 // declaration loop depth, increased for every loop or label
|
||||
Vargen int32 // unique name for ONAME within a function. Function outputs are numbered starting at one.
|
||||
Funcdepth int32
|
||||
@@ -280,15 +280,16 @@ type Param struct {
|
||||
Innermost *Node
|
||||
Outer *Node
|
||||
|
||||
// OTYPE pragmas
|
||||
// OTYPE
|
||||
//
|
||||
// TODO: Should Func pragmas also be stored on the Name?
|
||||
Pragma Pragma
|
||||
Alias bool // node is alias for Ntype (only used when type-checking ODCLTYPE)
|
||||
}
|
||||
|
||||
// Func holds Node fields used only with function-like nodes.
|
||||
type Func struct {
|
||||
Shortname *Node
|
||||
Shortname *Sym
|
||||
Enter Nodes // for example, allocate and initialize memory for escaping parameters
|
||||
Exit Nodes
|
||||
Cvars Nodes // closure params
|
||||
@@ -382,7 +383,7 @@ const (
|
||||
ODCLFUNC // func f() or func (r) f()
|
||||
ODCLFIELD // struct field, interface field, or func/method argument/return value.
|
||||
ODCLCONST // const pi = 3.14
|
||||
ODCLTYPE // type Int int
|
||||
ODCLTYPE // type Int int or type Int = int
|
||||
|
||||
ODELETE // delete(Left, Right)
|
||||
ODOT // Left.Sym (Left is of struct type)
|
||||
|
||||
@@ -96,16 +96,16 @@ func typekind(t *Type) string {
|
||||
return fmt.Sprintf("etype=%d", et)
|
||||
}
|
||||
|
||||
// sprint_depchain prints a dependency chain of nodes into fmt.
|
||||
// sprint_depchain prints a dependency chain of nodes into trace.
|
||||
// It is used by typecheck in the case of OLITERAL nodes
|
||||
// to print constant definition loops.
|
||||
func sprint_depchain(fmt_ *string, stack []*Node, cur *Node, first *Node) {
|
||||
func sprint_depchain(trace *string, stack []*Node, cur *Node, first *Node) {
|
||||
for i := len(stack) - 1; i >= 0; i-- {
|
||||
if n := stack[i]; n.Op == cur.Op {
|
||||
if n != first {
|
||||
sprint_depchain(fmt_, stack[:i], n, first)
|
||||
sprint_depchain(trace, stack[:i], n, first)
|
||||
}
|
||||
*fmt_ += fmt.Sprintf("\n\t%v: %v uses %v", n.Line(), n, cur)
|
||||
*trace += fmt.Sprintf("\n\t%v: %v uses %v", n.Line(), n, cur)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -152,7 +152,6 @@ func typecheck(n *Node, top int) *Node {
|
||||
if n.Typecheck == 2 {
|
||||
// Typechecking loop. Trying printing a meaningful message,
|
||||
// otherwise a stack trace of typechecking.
|
||||
var fmt_ string
|
||||
switch n.Op {
|
||||
// We can already diagnose variables used as types.
|
||||
case ONAME:
|
||||
@@ -160,22 +159,30 @@ func typecheck(n *Node, top int) *Node {
|
||||
yyerror("%v is not a type", n)
|
||||
}
|
||||
|
||||
case OTYPE:
|
||||
if top&Etype == Etype {
|
||||
var trace string
|
||||
sprint_depchain(&trace, typecheck_tcstack, n, n)
|
||||
yyerrorl(n.Lineno, "invalid recursive type alias %v%s", n, trace)
|
||||
}
|
||||
|
||||
case OLITERAL:
|
||||
if top&(Erv|Etype) == Etype {
|
||||
yyerror("%v is not a type", n)
|
||||
break
|
||||
}
|
||||
sprint_depchain(&fmt_, typecheck_tcstack, n, n)
|
||||
yyerrorl(n.Lineno, "constant definition loop%s", fmt_)
|
||||
var trace string
|
||||
sprint_depchain(&trace, typecheck_tcstack, n, n)
|
||||
yyerrorl(n.Lineno, "constant definition loop%s", trace)
|
||||
}
|
||||
|
||||
if nsavederrors+nerrors == 0 {
|
||||
fmt_ = ""
|
||||
var trace string
|
||||
for i := len(typecheck_tcstack) - 1; i >= 0; i-- {
|
||||
x := typecheck_tcstack[i]
|
||||
fmt_ += fmt.Sprintf("\n\t%v %v", x.Line(), x)
|
||||
trace += fmt.Sprintf("\n\t%v %v", x.Line(), x)
|
||||
}
|
||||
yyerror("typechecking loop involving %v%s", n, fmt_)
|
||||
yyerror("typechecking loop involving %v%s", n, trace)
|
||||
}
|
||||
|
||||
lineno = lno
|
||||
@@ -3428,7 +3435,14 @@ func typecheckfunc(n *Node) {
|
||||
t.SetNname(n.Func.Nname)
|
||||
rcvr := t.Recv()
|
||||
if rcvr != nil && n.Func.Shortname != nil {
|
||||
addmethod(n.Func.Shortname.Sym, t, true, n.Func.Pragma&Nointerface != 0)
|
||||
n.Func.Nname.Sym = methodname(n.Func.Shortname, rcvr.Type)
|
||||
declare(n.Func.Nname, PFUNC)
|
||||
|
||||
addmethod(n.Func.Shortname, t, true, n.Func.Pragma&Nointerface != 0)
|
||||
}
|
||||
|
||||
if Ctxt.Flag_dynlink && importpkg == nil && n.Func.Nname != nil {
|
||||
makefuncsym(n.Func.Nname.Sym)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3577,8 +3591,6 @@ func typecheckdeftype(n *Node) {
|
||||
|
||||
// copy new type and clear fields
|
||||
// that don't come along.
|
||||
// anything zeroed here must be zeroed in
|
||||
// typedcl2 too.
|
||||
copytype(n, t)
|
||||
|
||||
ret:
|
||||
@@ -3757,12 +3769,29 @@ func typecheckdef(n *Node) *Node {
|
||||
n.Name.Defn = typecheck(n.Name.Defn, Etop) // fills in n->type
|
||||
|
||||
case OTYPE:
|
||||
if p := n.Name.Param; p.Alias {
|
||||
// Type alias declaration: Simply use the rhs type - no need
|
||||
// to create a new type.
|
||||
// If we have a syntax error, p.Ntype may be nil.
|
||||
if p.Ntype != nil {
|
||||
p.Ntype = typecheck(p.Ntype, Etype)
|
||||
n.Type = p.Ntype.Type
|
||||
if n.Type == nil {
|
||||
n.Diag = true
|
||||
goto ret
|
||||
}
|
||||
n.Sym.Def = p.Ntype
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
// regular type declaration
|
||||
if Curfn != nil {
|
||||
defercheckwidth()
|
||||
}
|
||||
n.Walkdef = 1
|
||||
n.Type = typ(TFORW)
|
||||
n.Type.Sym = n.Sym
|
||||
n.Type.Sym = n.Sym // TODO(gri) this also happens in typecheckdeftype(n) - where should it happen?
|
||||
nerrors0 := nerrors
|
||||
typecheckdeftype(n)
|
||||
if n.Type.Etype == TFORW && nerrors > nerrors0 {
|
||||
@@ -3770,7 +3799,6 @@ func typecheckdef(n *Node) *Node {
|
||||
// but it was reported. Silence future errors.
|
||||
n.Type.Broke = true
|
||||
}
|
||||
|
||||
if Curfn != nil {
|
||||
resumecheckwidth()
|
||||
}
|
||||
|
||||
@@ -398,6 +398,14 @@ func lexinit1() {
|
||||
// errortype.Orig = makeErrorInterface()
|
||||
s.Def = typenod(errortype)
|
||||
|
||||
// We create separate byte and rune types for better error messages
|
||||
// rather than just creating type alias *Sym's for the uint8 and
|
||||
// int32 types. Hence, (bytetype|runtype).Sym.isAlias() is false.
|
||||
// TODO(gri) Should we get rid of this special case (at the cost
|
||||
// of less informative error messages involving bytes and runes)?
|
||||
// (Alternatively, we could introduce an OTALIAS node representing
|
||||
// type aliases, albeit at the cost of having to deal with it everywhere).
|
||||
|
||||
// byte alias
|
||||
s = Pkglookup("byte", builtinpkg)
|
||||
bytetype = typ(TUINT8)
|
||||
|
||||
@@ -74,6 +74,7 @@ type (
|
||||
// Name Type
|
||||
TypeDecl struct {
|
||||
Name *Name
|
||||
Alias bool
|
||||
Type Expr
|
||||
Group *Group // nil means not part of a group
|
||||
Pragma Pragma
|
||||
|
||||
@@ -325,7 +325,7 @@ func (p *parser) constDecl(group *Group) Decl {
|
||||
return d
|
||||
}
|
||||
|
||||
// TypeSpec = identifier Type .
|
||||
// TypeSpec = identifier [ "=" ] Type .
|
||||
func (p *parser) typeDecl(group *Group) Decl {
|
||||
if trace {
|
||||
defer p.trace("typeDecl")()
|
||||
@@ -335,6 +335,7 @@ func (p *parser) typeDecl(group *Group) Decl {
|
||||
d.init(p)
|
||||
|
||||
d.Name = p.name()
|
||||
d.Alias = p.got(_Assign)
|
||||
d.Type = p.tryType()
|
||||
if d.Type == nil {
|
||||
p.syntax_error("in type declaration")
|
||||
|
||||
@@ -619,7 +619,11 @@ func (p *printer) printRawNode(n Node) {
|
||||
if n.Group == nil {
|
||||
p.print(_Type, blank)
|
||||
}
|
||||
p.print(n.Name, blank, n.Type)
|
||||
p.print(n.Name, blank)
|
||||
if n.Alias {
|
||||
p.print(_Assign, blank)
|
||||
}
|
||||
p.print(n.Type)
|
||||
|
||||
case *VarDecl:
|
||||
if n.Group == nil {
|
||||
|
||||
@@ -22,3 +22,20 @@ func TestPrint(t *testing.T) {
|
||||
Fprint(os.Stdout, ast, true)
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func TestPrintString(t *testing.T) {
|
||||
for _, want := range []string{
|
||||
"package p",
|
||||
"package p; type _ = int; type T1 = struct{}; type ( _ = *struct{}; T2 = float32 )",
|
||||
// TODO(gri) expand
|
||||
} {
|
||||
ast, err := ParseBytes([]byte(want), nil, nil, 0)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
continue
|
||||
}
|
||||
if got := String(ast); got != want {
|
||||
t.Errorf("%q: got %q", want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1
src/cmd/dist/test.go
vendored
1
src/cmd/dist/test.go
vendored
@@ -600,6 +600,7 @@ func (t *tester) registerTests() {
|
||||
})
|
||||
}
|
||||
}
|
||||
return // skip API check on go1.8.typealias branch
|
||||
if t.goos != "nacl" && t.goos != "android" && !t.iOS() {
|
||||
t.tests = append(t.tests, distTest{
|
||||
name: "api",
|
||||
|
||||
@@ -71,6 +71,7 @@ var tests = []test{
|
||||
`const MultiLineConst = ...`, // Multi line constant.
|
||||
`var MultiLineVar = map\[struct{ ... }\]struct{ ... }{ ... }`, // Multi line variable.
|
||||
`func MultiLineFunc\(x interface{ ... }\) \(r struct{ ... }\)`, // Multi line function.
|
||||
`type T1 = T2`, // Type alias
|
||||
},
|
||||
[]string{
|
||||
`const internalConstant = 2`, // No internal constants.
|
||||
@@ -89,6 +90,7 @@ var tests = []test{
|
||||
`unexportedTypedConstant`, // No unexported typed constant.
|
||||
`Field`, // No fields.
|
||||
`Method`, // No methods.
|
||||
`type T1 T2`, // Type alias does not display as type declaration.
|
||||
},
|
||||
},
|
||||
// Package dump -u
|
||||
@@ -265,6 +267,18 @@ var tests = []test{
|
||||
`error`, // No embedded error.
|
||||
},
|
||||
},
|
||||
// Type T1 dump (alias).
|
||||
{
|
||||
"type T1",
|
||||
[]string{p+".T1"},
|
||||
[]string{
|
||||
`type T1 = T2`,
|
||||
},
|
||||
[]string{
|
||||
`type T1 T2`,
|
||||
`type ExportedType`,
|
||||
},
|
||||
},
|
||||
// Type -u with unexported fields.
|
||||
{
|
||||
"type with unexported fields and -u",
|
||||
|
||||
@@ -258,7 +258,11 @@ func (pkg *Package) oneLineNodeDepth(node ast.Node, depth int) string {
|
||||
return fmt.Sprintf("func %s%s%s", recv, name, fnc)
|
||||
|
||||
case *ast.TypeSpec:
|
||||
return fmt.Sprintf("type %s %s", n.Name.Name, pkg.oneLineNodeDepth(n.Type, depth))
|
||||
sep := " "
|
||||
if n.Assign.IsValid() {
|
||||
sep = " = "
|
||||
}
|
||||
return fmt.Sprintf("type %s%s%s", n.Name.Name, sep, pkg.oneLineNodeDepth(n.Type, depth))
|
||||
|
||||
case *ast.FuncType:
|
||||
var params []string
|
||||
|
||||
4
src/cmd/doc/testdata/pkg.go
vendored
4
src/cmd/doc/testdata/pkg.go
vendored
@@ -172,3 +172,7 @@ const (
|
||||
)
|
||||
|
||||
const ConstGroup4 ExportedType = ExportedType{}
|
||||
|
||||
type T2 int
|
||||
|
||||
type T1 = T2
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
// Copyright 2015 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 main_test
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestBoringInternalLink(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
tg.tempFile("main.go", `package main
|
||||
import "crypto/sha1"
|
||||
func main() {
|
||||
sha1.New()
|
||||
}`)
|
||||
tg.run("build", "-ldflags=-w -extld=false", tg.path("main.go"))
|
||||
tg.run("build", "-ldflags=-extld=false", tg.path("main.go"))
|
||||
}
|
||||
@@ -3497,8 +3497,8 @@ func TestBinaryOnlyPackages(t *testing.T) {
|
||||
tg.grepStdout("false", "did not see BinaryOnly=false for p4")
|
||||
}
|
||||
|
||||
// Issue 16050 and 21884.
|
||||
func TestLinkSysoFiles(t *testing.T) {
|
||||
// Issue 16050.
|
||||
func TestAlwaysLinkSysoFiles(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
@@ -3517,10 +3517,6 @@ func TestLinkSysoFiles(t *testing.T) {
|
||||
tg.setenv("CGO_ENABLED", "0")
|
||||
tg.run("list", "-f", "{{.SysoFiles}}", "syso")
|
||||
tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=0")
|
||||
|
||||
tg.setenv("CGO_ENABLED", "1")
|
||||
tg.run("list", "-msan", "-f", "{{.SysoFiles}}", "syso")
|
||||
tg.grepStdoutNot("a.syso", "unexpected syso file with -msan")
|
||||
}
|
||||
|
||||
// Issue 16120.
|
||||
|
||||
@@ -173,12 +173,6 @@ func (p *Package) copyBuild(pp *build.Package) {
|
||||
p.SwigFiles = pp.SwigFiles
|
||||
p.SwigCXXFiles = pp.SwigCXXFiles
|
||||
p.SysoFiles = pp.SysoFiles
|
||||
if buildMSan {
|
||||
// There's no way for .syso files to be built both with and without
|
||||
// support for memory sanitizer. Assume they are built without,
|
||||
// and drop them.
|
||||
p.SysoFiles = nil
|
||||
}
|
||||
p.CgoCFLAGS = pp.CgoCFLAGS
|
||||
p.CgoCPPFLAGS = pp.CgoCPPFLAGS
|
||||
p.CgoCXXFLAGS = pp.CgoCXXFLAGS
|
||||
|
||||
24
src/cmd/gofmt/testdata/typealias.golden
vendored
Normal file
24
src/cmd/gofmt/testdata/typealias.golden
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
package q
|
||||
|
||||
import "p"
|
||||
|
||||
type _ = int
|
||||
type a = struct{ x int }
|
||||
type b = p.B
|
||||
|
||||
type (
|
||||
_ = chan<- int
|
||||
aa = interface{}
|
||||
bb = p.BB
|
||||
)
|
||||
|
||||
// TODO(gri) We may want to put the '=' into a separate column if
|
||||
// we have mixed (regular and alias) type declarations in a group.
|
||||
type (
|
||||
_ chan<- int
|
||||
_ = chan<- int
|
||||
aa0 interface{}
|
||||
aaa = interface{}
|
||||
bb0 p.BB
|
||||
bbb = p.BB
|
||||
)
|
||||
24
src/cmd/gofmt/testdata/typealias.input
vendored
Normal file
24
src/cmd/gofmt/testdata/typealias.input
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
package q
|
||||
|
||||
import "p"
|
||||
|
||||
type _ = int
|
||||
type a = struct{ x int }
|
||||
type b = p.B
|
||||
|
||||
type (
|
||||
_ = chan<- int
|
||||
aa = interface{}
|
||||
bb = p.BB
|
||||
)
|
||||
|
||||
// TODO(gri) We may want to put the '=' into a separate column if
|
||||
// we have mixed (regular and alias) type declarations in a group.
|
||||
type (
|
||||
_ chan<- int
|
||||
_ = chan<- int
|
||||
aa0 interface{}
|
||||
aaa = interface{}
|
||||
bb0 p.BB
|
||||
bbb = p.BB
|
||||
)
|
||||
@@ -118,17 +118,6 @@ func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
|
||||
r.Add += 4
|
||||
return true
|
||||
|
||||
case 256 + ld.R_X86_64_PC64:
|
||||
if targ.Type == obj.SDYNIMPORT {
|
||||
ld.Errorf(s, "unexpected R_X86_64_PC64 relocation for dynamic symbol %s", targ.Name)
|
||||
}
|
||||
if targ.Type == 0 || targ.Type == obj.SXREF {
|
||||
ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name)
|
||||
}
|
||||
r.Type = obj.R_PCREL
|
||||
r.Add += 8
|
||||
return true
|
||||
|
||||
case 256 + ld.R_X86_64_PLT32:
|
||||
r.Type = obj.R_PCREL
|
||||
r.Add += 4
|
||||
|
||||
@@ -1836,11 +1836,6 @@ func (ctxt *Link) dodata() {
|
||||
datsize = Rnd(datsize, int64(sect.Align))
|
||||
sect.Vaddr = uint64(datsize)
|
||||
for _, s := range dwarfp[i:] {
|
||||
// Syms can (incorrectly) appear twice on the list. Ignore repeats.
|
||||
// See golang.org/issue/21566.
|
||||
if s.Type == obj.SRODATA {
|
||||
continue
|
||||
}
|
||||
if s.Type != obj.SDWARFINFO {
|
||||
break
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ func decodetypeStructFieldType(s *Symbol, i int) *Symbol {
|
||||
|
||||
func decodetypeStructFieldOffs(arch *sys.Arch, s *Symbol, i int) int64 {
|
||||
off := decodetypeStructFieldArrayOff(s, i)
|
||||
return int64(decodeInuxi(arch, s.P[off+2*SysArch.PtrSize:], SysArch.IntSize))
|
||||
return int64(decodeInuxi(arch, s.P[off+2*SysArch.PtrSize:], SysArch.IntSize) >> 1)
|
||||
}
|
||||
|
||||
// InterfaceType.methods.length
|
||||
|
||||
@@ -1201,7 +1201,6 @@ func relSize(ctxt *Link, pn string, elftype uint32) uint8 {
|
||||
return 4
|
||||
|
||||
case AMD64 | R_X86_64_64<<24,
|
||||
AMD64 | R_X86_64_PC64<<24,
|
||||
PPC64 | R_PPC64_ADDR64<<24,
|
||||
S390X | R_390_GLOB_DAT<<24,
|
||||
S390X | R_390_RELATIVE<<24,
|
||||
|
||||
@@ -808,7 +808,6 @@ var hostobj []Hostobj
|
||||
// These packages can use internal linking mode.
|
||||
// Others trigger external mode.
|
||||
var internalpkg = []string{
|
||||
"crypto/internal/boring",
|
||||
"crypto/x509",
|
||||
"net",
|
||||
"os/user",
|
||||
|
||||
@@ -6,7 +6,6 @@ package aes
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"crypto/internal/boring"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
@@ -37,9 +36,6 @@ func NewCipher(key []byte) (cipher.Block, error) {
|
||||
case 16, 24, 32:
|
||||
break
|
||||
}
|
||||
if boring.Enabled {
|
||||
return boring.NewAESCipher(key)
|
||||
}
|
||||
return newCipher(key)
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ package aes
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"crypto/internal/boring"
|
||||
"crypto/internal/cipherhw"
|
||||
)
|
||||
|
||||
@@ -47,7 +46,6 @@ func newCipher(key []byte) (cipher.Block, error) {
|
||||
func (c *aesCipherAsm) BlockSize() int { return BlockSize }
|
||||
|
||||
func (c *aesCipherAsm) Encrypt(dst, src []byte) {
|
||||
boring.Unreachable()
|
||||
if len(src) < BlockSize {
|
||||
panic("crypto/aes: input not full block")
|
||||
}
|
||||
@@ -58,7 +56,6 @@ func (c *aesCipherAsm) Encrypt(dst, src []byte) {
|
||||
}
|
||||
|
||||
func (c *aesCipherAsm) Decrypt(dst, src []byte) {
|
||||
boring.Unreachable()
|
||||
if len(src) < BlockSize {
|
||||
panic("crypto/aes: input not full block")
|
||||
}
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
// Copyright 2017 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 ecdsa
|
||||
|
||||
import (
|
||||
"crypto/internal/boring"
|
||||
"math/big"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Cached conversions from Go PublicKey/PrivateKey to BoringCrypto.
|
||||
//
|
||||
// A new 'boring atomic.Value' field in both PublicKey and PrivateKey
|
||||
// serves as a cache for the most recent conversion. The cache is an
|
||||
// atomic.Value because code might reasonably set up a key and then
|
||||
// (thinking it immutable) use it from multiple goroutines simultaneously.
|
||||
// The first operation initializes the cache; if there are multiple simultaneous
|
||||
// first operations, they will do redundant work but not step on each other.
|
||||
//
|
||||
// We could just assume that once used in a Sign or Verify operation,
|
||||
// a particular key is never again modified, but that has not been a
|
||||
// stated assumption before. Just in case there is any existing code that
|
||||
// does modify the key between operations, we save the original values
|
||||
// alongside the cached BoringCrypto key and check that the real key
|
||||
// still matches before using the cached key. The theory is that the real
|
||||
// operations are significantly more expensive than the comparison.
|
||||
|
||||
type boringPub struct {
|
||||
key *boring.PublicKeyECDSA
|
||||
orig PublicKey
|
||||
}
|
||||
|
||||
func boringPublicKey(pub *PublicKey) (*boring.PublicKeyECDSA, error) {
|
||||
b := (*boringPub)(atomic.LoadPointer(&pub.boring))
|
||||
if b != nil && publicKeyEqual(&b.orig, pub) {
|
||||
return b.key, nil
|
||||
}
|
||||
|
||||
b = new(boringPub)
|
||||
b.orig = copyPublicKey(pub)
|
||||
key, err := boring.NewPublicKeyECDSA(b.orig.Curve.Params().Name, b.orig.X, b.orig.Y)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b.key = key
|
||||
atomic.StorePointer(&pub.boring, unsafe.Pointer(b))
|
||||
return key, nil
|
||||
}
|
||||
|
||||
type boringPriv struct {
|
||||
key *boring.PrivateKeyECDSA
|
||||
orig PrivateKey
|
||||
}
|
||||
|
||||
func boringPrivateKey(priv *PrivateKey) (*boring.PrivateKeyECDSA, error) {
|
||||
b := (*boringPriv)(atomic.LoadPointer(&priv.boring))
|
||||
if b != nil && privateKeyEqual(&b.orig, priv) {
|
||||
return b.key, nil
|
||||
}
|
||||
|
||||
b = new(boringPriv)
|
||||
b.orig = copyPrivateKey(priv)
|
||||
key, err := boring.NewPrivateKeyECDSA(b.orig.Curve.Params().Name, b.orig.X, b.orig.Y, b.orig.D)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b.key = key
|
||||
atomic.StorePointer(&priv.boring, unsafe.Pointer(b))
|
||||
return key, nil
|
||||
}
|
||||
|
||||
func publicKeyEqual(k1, k2 *PublicKey) bool {
|
||||
return k1.X != nil &&
|
||||
k1.Curve.Params() == k2.Curve.Params() &&
|
||||
k1.X.Cmp(k2.X) == 0 &&
|
||||
k1.Y.Cmp(k2.Y) == 0
|
||||
}
|
||||
|
||||
func privateKeyEqual(k1, k2 *PrivateKey) bool {
|
||||
return publicKeyEqual(&k1.PublicKey, &k2.PublicKey) &&
|
||||
k1.D.Cmp(k2.D) == 0
|
||||
}
|
||||
|
||||
func copyPublicKey(k *PublicKey) PublicKey {
|
||||
return PublicKey{
|
||||
Curve: k.Curve,
|
||||
X: new(big.Int).Set(k.X),
|
||||
Y: new(big.Int).Set(k.Y),
|
||||
}
|
||||
}
|
||||
|
||||
func copyPrivateKey(k *PrivateKey) PrivateKey {
|
||||
return PrivateKey{
|
||||
PublicKey: copyPublicKey(&k.PublicKey),
|
||||
D: new(big.Int).Set(k.D),
|
||||
}
|
||||
}
|
||||
@@ -21,13 +21,11 @@ import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/elliptic"
|
||||
"crypto/internal/boring"
|
||||
"crypto/sha512"
|
||||
"encoding/asn1"
|
||||
"errors"
|
||||
"io"
|
||||
"math/big"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// A invertible implements fast inverse mod Curve.Params().N
|
||||
@@ -49,16 +47,12 @@ const (
|
||||
type PublicKey struct {
|
||||
elliptic.Curve
|
||||
X, Y *big.Int
|
||||
|
||||
boring unsafe.Pointer
|
||||
}
|
||||
|
||||
// PrivateKey represents a ECDSA private key.
|
||||
type PrivateKey struct {
|
||||
PublicKey
|
||||
D *big.Int
|
||||
|
||||
boring unsafe.Pointer
|
||||
}
|
||||
|
||||
type ecdsaSignature struct {
|
||||
@@ -75,15 +69,6 @@ func (priv *PrivateKey) Public() crypto.PublicKey {
|
||||
// hardware module. Common uses should use the Sign function in this package
|
||||
// directly.
|
||||
func (priv *PrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) ([]byte, error) {
|
||||
if boring.Enabled && rand == boring.RandReader {
|
||||
b, err := boringPrivateKey(priv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return boring.SignMarshalECDSA(b, msg)
|
||||
}
|
||||
boring.UnreachableExceptTests()
|
||||
|
||||
r, s, err := Sign(rand, priv, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -113,15 +98,6 @@ func randFieldElement(c elliptic.Curve, rand io.Reader) (k *big.Int, err error)
|
||||
|
||||
// GenerateKey generates a public and private key pair.
|
||||
func GenerateKey(c elliptic.Curve, rand io.Reader) (*PrivateKey, error) {
|
||||
if boring.Enabled && rand == boring.RandReader {
|
||||
x, y, d, err := boring.GenerateKeyECDSA(c.Params().Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &PrivateKey{PublicKey: PublicKey{Curve: c, X: x, Y: y}, D: d}, nil
|
||||
}
|
||||
boring.UnreachableExceptTests()
|
||||
|
||||
k, err := randFieldElement(c, rand)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -173,15 +149,6 @@ var errZeroParam = errors.New("zero parameter")
|
||||
// returns the signature as a pair of integers. The security of the private key
|
||||
// depends on the entropy of rand.
|
||||
func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) {
|
||||
if boring.Enabled && rand == boring.RandReader {
|
||||
b, err := boringPrivateKey(priv)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return boring.SignECDSA(b, hash)
|
||||
}
|
||||
boring.UnreachableExceptTests()
|
||||
|
||||
// Get min(log2(q) / 2, 256) bits of entropy from rand.
|
||||
entropylen := (priv.Curve.Params().BitSize + 7) / 16
|
||||
if entropylen > 32 {
|
||||
@@ -258,15 +225,6 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err
|
||||
// Verify verifies the signature in r, s of hash using the public key, pub. Its
|
||||
// return value records whether the signature is valid.
|
||||
func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
|
||||
if boring.Enabled {
|
||||
b, err := boringPublicKey(pub)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return boring.VerifyECDSA(b, hash, r, s)
|
||||
}
|
||||
boring.UnreachableExceptTests()
|
||||
|
||||
// See [NSA] 3.4.2
|
||||
c := pub.Curve
|
||||
N := c.Params().N
|
||||
|
||||
@@ -22,7 +22,6 @@ timing side-channels:
|
||||
package hmac
|
||||
|
||||
import (
|
||||
"crypto/internal/boring"
|
||||
"crypto/subtle"
|
||||
"hash"
|
||||
)
|
||||
@@ -66,13 +65,6 @@ func (h *hmac) Reset() {
|
||||
|
||||
// New returns a new HMAC hash using the given hash.Hash type and key.
|
||||
func New(h func() hash.Hash, key []byte) hash.Hash {
|
||||
if boring.Enabled {
|
||||
hm := boring.NewHMAC(h, key)
|
||||
if hm != nil {
|
||||
return hm
|
||||
}
|
||||
// BoringCrypto did not recognize h, so fall through to standard Go code.
|
||||
}
|
||||
hm := new(hmac)
|
||||
hm.outer = h()
|
||||
hm.inner = h()
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
package hmac
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
@@ -519,31 +518,6 @@ var hmacTests = []hmacTest{
|
||||
sha512.Size,
|
||||
sha512.BlockSize,
|
||||
},
|
||||
// HMAC without key is dumb but should probably not fail.
|
||||
{
|
||||
sha1.New,
|
||||
[]byte{},
|
||||
[]byte("message"),
|
||||
"d5d1ed05121417247616cfc8378f360a39da7cfa",
|
||||
sha1.Size,
|
||||
sha1.BlockSize,
|
||||
},
|
||||
{
|
||||
sha256.New,
|
||||
[]byte{},
|
||||
[]byte("message"),
|
||||
"eb08c1f56d5ddee07f7bdf80468083da06b64cf4fac64fe3a90883df5feacae4",
|
||||
sha256.Size,
|
||||
sha256.BlockSize,
|
||||
},
|
||||
{
|
||||
sha512.New,
|
||||
[]byte{},
|
||||
[]byte("message"),
|
||||
"08fce52f6395d59c2a3fb8abb281d74ad6f112b9a9c787bcea290d94dadbc82b2ca3e5e12bf2277c7fedbb0154d5493e41bb7459f63c8e39554ea3651b812492",
|
||||
sha512.Size,
|
||||
sha512.BlockSize,
|
||||
},
|
||||
}
|
||||
|
||||
func TestHMAC(t *testing.T) {
|
||||
@@ -595,42 +569,6 @@ func TestEqual(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteAfterSum(t *testing.T) {
|
||||
h := New(sha1.New, nil)
|
||||
h.Write([]byte("hello"))
|
||||
sumHello := h.Sum(nil)
|
||||
|
||||
h = New(sha1.New, nil)
|
||||
h.Write([]byte("hello world"))
|
||||
sumHelloWorld := h.Sum(nil)
|
||||
|
||||
// Test that Sum has no effect on future Sum or Write operations.
|
||||
// This is a bit unusual as far as usage, but it's allowed
|
||||
// by the definition of Go hash.Hash, and some clients expect it to work.
|
||||
h = New(sha1.New, nil)
|
||||
h.Write([]byte("hello"))
|
||||
if sum := h.Sum(nil); !bytes.Equal(sum, sumHello) {
|
||||
t.Fatalf("1st Sum after hello = %x, want %x", sum, sumHello)
|
||||
}
|
||||
if sum := h.Sum(nil); !bytes.Equal(sum, sumHello) {
|
||||
t.Fatalf("2nd Sum after hello = %x, want %x", sum, sumHello)
|
||||
}
|
||||
|
||||
h.Write([]byte(" world"))
|
||||
if sum := h.Sum(nil); !bytes.Equal(sum, sumHelloWorld) {
|
||||
t.Fatalf("1st Sum after hello world = %x, want %x", sum, sumHelloWorld)
|
||||
}
|
||||
if sum := h.Sum(nil); !bytes.Equal(sum, sumHelloWorld) {
|
||||
t.Fatalf("2nd Sum after hello world = %x, want %x", sum, sumHelloWorld)
|
||||
}
|
||||
|
||||
h.Reset()
|
||||
h.Write([]byte("hello"))
|
||||
if sum := h.Sum(nil); !bytes.Equal(sum, sumHello) {
|
||||
t.Fatalf("Sum after Reset + hello = %x, want %x", sum, sumHello)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkHMACSHA256_1K(b *testing.B) {
|
||||
key := make([]byte, 32)
|
||||
buf := make([]byte, 1024)
|
||||
|
||||
@@ -1,200 +0,0 @@
|
||||
The Go source code and supporting files in this directory
|
||||
are covered by the usual Go license (see ../../../../LICENSE).
|
||||
|
||||
The goboringcrypto_linux_amd64.syso object file is built
|
||||
from BoringSSL source code by build/build.sh and is covered
|
||||
by the BoringSSL license reproduced below and also at
|
||||
https://boringssl.googlesource.com/boringssl/+/fips-20170615/LICENSE.
|
||||
|
||||
BoringSSL is a fork of OpenSSL. As such, large parts of it fall under OpenSSL
|
||||
licensing. Files that are completely new have a Google copyright and an ISC
|
||||
license. This license is reproduced at the bottom of this file.
|
||||
|
||||
Contributors to BoringSSL are required to follow the CLA rules for Chromium:
|
||||
https://cla.developers.google.com/clas
|
||||
|
||||
Some files from Intel are under yet another license, which is also included
|
||||
underneath.
|
||||
|
||||
The OpenSSL toolkit stays under a dual license, i.e. both the conditions of the
|
||||
OpenSSL License and the original SSLeay license apply to the toolkit. See below
|
||||
for the actual license texts. Actually both licenses are BSD-style Open Source
|
||||
licenses. In case of any license issues related to OpenSSL please contact
|
||||
openssl-core@openssl.org.
|
||||
|
||||
The following are Google-internal bug numbers where explicit permission from
|
||||
some authors is recorded for use of their work. (This is purely for our own
|
||||
record keeping.)
|
||||
27287199
|
||||
27287880
|
||||
27287883
|
||||
|
||||
OpenSSL License
|
||||
---------------
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
Original SSLeay License
|
||||
-----------------------
|
||||
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
|
||||
ISC license used for completely new code in BoringSSL:
|
||||
|
||||
/* Copyright (c) 2015, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
|
||||
Some files from Intel carry the following license:
|
||||
|
||||
# Copyright (c) 2012, Intel Corporation
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# * Neither the name of the Intel Corporation nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION ""AS IS"" AND ANY
|
||||
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR
|
||||
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -1,357 +0,0 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build linux,amd64
|
||||
// +build !android
|
||||
// +build !cmd_go_bootstrap
|
||||
// +build !msan
|
||||
|
||||
package boring
|
||||
|
||||
// #include "goboringcrypto.h"
|
||||
import "C"
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"errors"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type aesKeySizeError int
|
||||
|
||||
func (k aesKeySizeError) Error() string {
|
||||
return "crypto/aes: invalid key size " + strconv.Itoa(int(k))
|
||||
}
|
||||
|
||||
const aesBlockSize = 16
|
||||
|
||||
type aesCipher struct {
|
||||
key []byte
|
||||
enc C.GO_AES_KEY
|
||||
dec C.GO_AES_KEY
|
||||
}
|
||||
|
||||
type extraModes interface {
|
||||
// Copied out of crypto/aes/modes.go.
|
||||
NewCBCEncrypter(iv []byte) cipher.BlockMode
|
||||
NewCBCDecrypter(iv []byte) cipher.BlockMode
|
||||
NewCTR(iv []byte) cipher.Stream
|
||||
NewGCM(nonceSize int) (cipher.AEAD, error)
|
||||
|
||||
// Invented for BoringCrypto.
|
||||
NewGCMTLS() (cipher.AEAD, error)
|
||||
}
|
||||
|
||||
var _ extraModes = (*aesCipher)(nil)
|
||||
|
||||
func NewAESCipher(key []byte) (cipher.Block, error) {
|
||||
c := &aesCipher{key: make([]byte, len(key))}
|
||||
copy(c.key, key)
|
||||
// Note: 0 is success, contradicting the usual BoringCrypto convention.
|
||||
if C._goboringcrypto_AES_set_decrypt_key((*C.uint8_t)(unsafe.Pointer(&c.key[0])), C.uint(8*len(c.key)), &c.dec) != 0 ||
|
||||
C._goboringcrypto_AES_set_encrypt_key((*C.uint8_t)(unsafe.Pointer(&c.key[0])), C.uint(8*len(c.key)), &c.enc) != 0 {
|
||||
return nil, aesKeySizeError(len(key))
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (c *aesCipher) BlockSize() int { return aesBlockSize }
|
||||
|
||||
func (c *aesCipher) Encrypt(dst, src []byte) {
|
||||
if inexactOverlap(dst, src) {
|
||||
panic("crypto/cipher: invalid buffer overlap")
|
||||
}
|
||||
if len(src) < aesBlockSize {
|
||||
panic("crypto/aes: input not full block")
|
||||
}
|
||||
if len(dst) < aesBlockSize {
|
||||
panic("crypto/aes: output not full block")
|
||||
}
|
||||
C._goboringcrypto_AES_encrypt(
|
||||
(*C.uint8_t)(unsafe.Pointer(&src[0])),
|
||||
(*C.uint8_t)(unsafe.Pointer(&dst[0])),
|
||||
&c.enc)
|
||||
}
|
||||
|
||||
func (c *aesCipher) Decrypt(dst, src []byte) {
|
||||
if inexactOverlap(dst, src) {
|
||||
panic("crypto/cipher: invalid buffer overlap")
|
||||
}
|
||||
if len(src) < aesBlockSize {
|
||||
panic("crypto/aes: input not full block")
|
||||
}
|
||||
if len(dst) < aesBlockSize {
|
||||
panic("crypto/aes: output not full block")
|
||||
}
|
||||
C._goboringcrypto_AES_decrypt(
|
||||
(*C.uint8_t)(unsafe.Pointer(&src[0])),
|
||||
(*C.uint8_t)(unsafe.Pointer(&dst[0])),
|
||||
&c.dec)
|
||||
}
|
||||
|
||||
type aesCBC struct {
|
||||
key *C.GO_AES_KEY
|
||||
mode C.int
|
||||
iv [aesBlockSize]byte
|
||||
}
|
||||
|
||||
func (x *aesCBC) BlockSize() int { return aesBlockSize }
|
||||
|
||||
func (x *aesCBC) CryptBlocks(dst, src []byte) {
|
||||
if inexactOverlap(dst, src) {
|
||||
panic("crypto/cipher: invalid buffer overlap")
|
||||
}
|
||||
if len(src)%aesBlockSize != 0 {
|
||||
panic("crypto/cipher: input not full blocks")
|
||||
}
|
||||
if len(dst) < len(src) {
|
||||
panic("crypto/cipher: output smaller than input")
|
||||
}
|
||||
if len(src) > 0 {
|
||||
C._goboringcrypto_AES_cbc_encrypt(
|
||||
(*C.uint8_t)(unsafe.Pointer(&src[0])),
|
||||
(*C.uint8_t)(unsafe.Pointer(&dst[0])),
|
||||
C.size_t(len(src)), x.key,
|
||||
(*C.uint8_t)(unsafe.Pointer(&x.iv[0])), x.mode)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *aesCBC) SetIV(iv []byte) {
|
||||
if len(iv) != aesBlockSize {
|
||||
panic("cipher: incorrect length IV")
|
||||
}
|
||||
copy(x.iv[:], iv)
|
||||
}
|
||||
|
||||
func (c *aesCipher) NewCBCEncrypter(iv []byte) cipher.BlockMode {
|
||||
x := &aesCBC{key: &c.enc, mode: C.GO_AES_ENCRYPT}
|
||||
copy(x.iv[:], iv)
|
||||
return x
|
||||
}
|
||||
|
||||
func (c *aesCipher) NewCBCDecrypter(iv []byte) cipher.BlockMode {
|
||||
x := &aesCBC{key: &c.dec, mode: C.GO_AES_DECRYPT}
|
||||
copy(x.iv[:], iv)
|
||||
return x
|
||||
}
|
||||
|
||||
type aesCTR struct {
|
||||
key *C.GO_AES_KEY
|
||||
iv [aesBlockSize]byte
|
||||
num C.uint
|
||||
ecount_buf [16]C.uint8_t
|
||||
}
|
||||
|
||||
func (x *aesCTR) XORKeyStream(dst, src []byte) {
|
||||
if inexactOverlap(dst, src) {
|
||||
panic("crypto/cipher: invalid buffer overlap")
|
||||
}
|
||||
if len(dst) < len(src) {
|
||||
panic("crypto/cipher: output smaller than input")
|
||||
}
|
||||
if len(src) == 0 {
|
||||
return
|
||||
}
|
||||
C._goboringcrypto_AES_ctr128_encrypt(
|
||||
(*C.uint8_t)(unsafe.Pointer(&src[0])),
|
||||
(*C.uint8_t)(unsafe.Pointer(&dst[0])),
|
||||
C.size_t(len(src)), x.key, (*C.uint8_t)(unsafe.Pointer(&x.iv[0])),
|
||||
&x.ecount_buf[0], &x.num)
|
||||
}
|
||||
|
||||
func (c *aesCipher) NewCTR(iv []byte) cipher.Stream {
|
||||
x := &aesCTR{key: &c.enc}
|
||||
copy(x.iv[:], iv)
|
||||
return x
|
||||
}
|
||||
|
||||
type aesGCM struct {
|
||||
ctx C.GO_EVP_AEAD_CTX
|
||||
aead *C.GO_EVP_AEAD
|
||||
}
|
||||
|
||||
const (
|
||||
gcmBlockSize = 16
|
||||
gcmTagSize = 16
|
||||
gcmStandardNonceSize = 12
|
||||
)
|
||||
|
||||
type aesNonceSizeError int
|
||||
|
||||
func (n aesNonceSizeError) Error() string {
|
||||
return "crypto/aes: invalid GCM nonce size " + strconv.Itoa(int(n))
|
||||
}
|
||||
|
||||
type noGCM struct {
|
||||
cipher.Block
|
||||
}
|
||||
|
||||
func (c *aesCipher) NewGCM(nonceSize int) (cipher.AEAD, error) {
|
||||
return c.newGCM(nonceSize, false)
|
||||
}
|
||||
|
||||
func (c *aesCipher) NewGCMTLS() (cipher.AEAD, error) {
|
||||
return c.newGCM(gcmStandardNonceSize, true)
|
||||
}
|
||||
|
||||
func (c *aesCipher) newGCM(nonceSize int, tls bool) (cipher.AEAD, error) {
|
||||
if nonceSize != gcmStandardNonceSize {
|
||||
// Fall back to standard library for GCM with non-standard nonce size.
|
||||
return cipher.NewGCMWithNonceSize(&noGCM{c}, nonceSize)
|
||||
}
|
||||
|
||||
var aead *C.GO_EVP_AEAD
|
||||
switch len(c.key) * 8 {
|
||||
case 128:
|
||||
if tls {
|
||||
aead = C._goboringcrypto_EVP_aead_aes_128_gcm_tls12()
|
||||
} else {
|
||||
aead = C._goboringcrypto_EVP_aead_aes_128_gcm()
|
||||
}
|
||||
case 256:
|
||||
if tls {
|
||||
aead = C._goboringcrypto_EVP_aead_aes_256_gcm_tls12()
|
||||
} else {
|
||||
aead = C._goboringcrypto_EVP_aead_aes_256_gcm()
|
||||
}
|
||||
default:
|
||||
// Fall back to standard library for GCM with non-standard key size.
|
||||
return cipher.NewGCMWithNonceSize(&noGCM{c}, nonceSize)
|
||||
}
|
||||
|
||||
g := &aesGCM{aead: aead}
|
||||
if C._goboringcrypto_EVP_AEAD_CTX_init(&g.ctx, aead, (*C.uint8_t)(unsafe.Pointer(&c.key[0])), C.size_t(len(c.key)), C.GO_EVP_AEAD_DEFAULT_TAG_LENGTH, nil) == 0 {
|
||||
return nil, fail("EVP_AEAD_CTX_init")
|
||||
}
|
||||
// Note: Because of the finalizer, any time g.ctx is passed to cgo,
|
||||
// that call must be followed by a call to runtime.KeepAlive(g),
|
||||
// to make sure g is not collected (and finalized) before the cgo
|
||||
// call returns.
|
||||
runtime.SetFinalizer(g, (*aesGCM).finalize)
|
||||
if g.NonceSize() != nonceSize {
|
||||
panic("boringcrypto: internal confusion about nonce size")
|
||||
}
|
||||
if g.Overhead() != gcmTagSize {
|
||||
panic("boringcrypto: internal confusion about tag size")
|
||||
}
|
||||
|
||||
return g, nil
|
||||
}
|
||||
|
||||
func (g *aesGCM) finalize() {
|
||||
C._goboringcrypto_EVP_AEAD_CTX_cleanup(&g.ctx)
|
||||
}
|
||||
|
||||
func (g *aesGCM) NonceSize() int {
|
||||
return int(C._goboringcrypto_EVP_AEAD_nonce_length(g.aead))
|
||||
}
|
||||
|
||||
func (g *aesGCM) Overhead() int {
|
||||
return int(C._goboringcrypto_EVP_AEAD_max_overhead(g.aead))
|
||||
}
|
||||
|
||||
// base returns the address of the underlying array in b,
|
||||
// being careful not to panic when b has zero length.
|
||||
func base(b []byte) *C.uint8_t {
|
||||
if len(b) == 0 {
|
||||
return nil
|
||||
}
|
||||
return (*C.uint8_t)(unsafe.Pointer(&b[0]))
|
||||
}
|
||||
|
||||
func (g *aesGCM) Seal(dst, nonce, plaintext, additionalData []byte) []byte {
|
||||
if len(nonce) != gcmStandardNonceSize {
|
||||
panic("cipher: incorrect nonce length given to GCM")
|
||||
}
|
||||
if uint64(len(plaintext)) > ((1<<32)-2)*aesBlockSize || len(plaintext)+gcmTagSize < len(plaintext) {
|
||||
panic("cipher: message too large for GCM")
|
||||
}
|
||||
if len(dst)+len(plaintext)+gcmTagSize < len(dst) {
|
||||
panic("cipher: message too large for buffer")
|
||||
}
|
||||
|
||||
// Make room in dst to append plaintext+overhead.
|
||||
n := len(dst)
|
||||
for cap(dst) < n+len(plaintext)+gcmTagSize {
|
||||
dst = append(dst[:cap(dst)], 0)
|
||||
}
|
||||
dst = dst[:n+len(plaintext)+gcmTagSize]
|
||||
|
||||
// Check delayed until now to make sure len(dst) is accurate.
|
||||
if inexactOverlap(dst[n:], plaintext) {
|
||||
panic("cipher: invalid buffer overlap")
|
||||
}
|
||||
|
||||
var outLen C.size_t
|
||||
ok := C._goboringcrypto_EVP_AEAD_CTX_seal(
|
||||
&g.ctx,
|
||||
(*C.uint8_t)(unsafe.Pointer(&dst[n])), &outLen, C.size_t(len(plaintext)+gcmTagSize),
|
||||
base(nonce), C.size_t(len(nonce)),
|
||||
base(plaintext), C.size_t(len(plaintext)),
|
||||
base(additionalData), C.size_t(len(additionalData)))
|
||||
runtime.KeepAlive(g)
|
||||
if ok == 0 {
|
||||
panic(fail("EVP_AEAD_CTX_seal"))
|
||||
}
|
||||
if outLen != C.size_t(len(plaintext)+gcmTagSize) {
|
||||
panic("boringcrypto: internal confusion about GCM tag size")
|
||||
}
|
||||
return dst[:n+int(outLen)]
|
||||
}
|
||||
|
||||
var errOpen = errors.New("cipher: message authentication failed")
|
||||
|
||||
func (g *aesGCM) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
|
||||
if len(nonce) != gcmStandardNonceSize {
|
||||
panic("cipher: incorrect nonce length given to GCM")
|
||||
}
|
||||
if len(ciphertext) < gcmTagSize {
|
||||
return nil, errOpen
|
||||
}
|
||||
if uint64(len(ciphertext)) > ((1<<32)-2)*aesBlockSize+gcmTagSize {
|
||||
return nil, errOpen
|
||||
}
|
||||
|
||||
// Make room in dst to append ciphertext without tag.
|
||||
n := len(dst)
|
||||
for cap(dst) < n+len(ciphertext)-gcmTagSize {
|
||||
dst = append(dst[:cap(dst)], 0)
|
||||
}
|
||||
dst = dst[:n+len(ciphertext)-gcmTagSize]
|
||||
|
||||
// Check delayed until now to make sure len(dst) is accurate.
|
||||
if inexactOverlap(dst[n:], ciphertext) {
|
||||
panic("cipher: invalid buffer overlap")
|
||||
}
|
||||
|
||||
var outLen C.size_t
|
||||
ok := C._goboringcrypto_EVP_AEAD_CTX_open(
|
||||
&g.ctx,
|
||||
base(dst[n:]), &outLen, C.size_t(len(ciphertext)-gcmTagSize),
|
||||
base(nonce), C.size_t(len(nonce)),
|
||||
base(ciphertext), C.size_t(len(ciphertext)),
|
||||
base(additionalData), C.size_t(len(additionalData)))
|
||||
runtime.KeepAlive(g)
|
||||
if ok == 0 {
|
||||
return nil, errOpen
|
||||
}
|
||||
if outLen != C.size_t(len(ciphertext)-gcmTagSize) {
|
||||
panic("boringcrypto: internal confusion about GCM tag size")
|
||||
}
|
||||
return dst[:n+int(outLen)], nil
|
||||
}
|
||||
|
||||
func anyOverlap(x, y []byte) bool {
|
||||
return len(x) > 0 && len(y) > 0 &&
|
||||
uintptr(unsafe.Pointer(&x[0])) <= uintptr(unsafe.Pointer(&y[len(y)-1])) &&
|
||||
uintptr(unsafe.Pointer(&y[0])) <= uintptr(unsafe.Pointer(&x[len(x)-1]))
|
||||
}
|
||||
|
||||
func inexactOverlap(x, y []byte) bool {
|
||||
if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] {
|
||||
return false
|
||||
}
|
||||
return anyOverlap(x, y)
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build linux,amd64
|
||||
// +build !android
|
||||
// +build !cmd_go_bootstrap
|
||||
// +build !msan
|
||||
|
||||
package boring
|
||||
|
||||
// #include "goboringcrypto.h"
|
||||
import "C"
|
||||
import (
|
||||
"crypto/internal/boring/sig"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
const available = true
|
||||
|
||||
func init() {
|
||||
C._goboringcrypto_BORINGSSL_bcm_power_on_self_test()
|
||||
if C._goboringcrypto_FIPS_mode() != 1 {
|
||||
panic("boringcrypto: not in FIPS mode")
|
||||
}
|
||||
sig.BoringCrypto()
|
||||
}
|
||||
|
||||
// Unreachable marks code that should be unreachable
|
||||
// when BoringCrypto is in use. It panics.
|
||||
func Unreachable() {
|
||||
panic("boringcrypto: invalid code execution")
|
||||
}
|
||||
|
||||
// provided by runtime to avoid os import
|
||||
func runtime_arg0() string
|
||||
|
||||
func hasSuffix(s, t string) bool {
|
||||
return len(s) > len(t) && s[len(s)-len(t):] == t
|
||||
}
|
||||
|
||||
// UnreachableExceptTests marks code that should be unreachable
|
||||
// when BoringCrypto is in use. It panics.
|
||||
func UnreachableExceptTests() {
|
||||
name := runtime_arg0()
|
||||
// If BoringCrypto ran on Windows we'd need to allow _test.exe and .test.exe as well.
|
||||
if !hasSuffix(name, "_test") && !hasSuffix(name, ".test") {
|
||||
println("boringcrypto: unexpected code execution in", name)
|
||||
panic("boringcrypto: invalid code execution")
|
||||
}
|
||||
}
|
||||
|
||||
type fail string
|
||||
|
||||
func (e fail) Error() string { return "boringcrypto: " + string(e) + " failed" }
|
||||
|
||||
func bigToBN(x *big.Int) *C.GO_BIGNUM {
|
||||
raw := x.Bytes()
|
||||
return C._goboringcrypto_BN_bin2bn(base(raw), C.size_t(len(raw)), nil)
|
||||
}
|
||||
|
||||
func bnToBig(bn *C.GO_BIGNUM) *big.Int {
|
||||
raw := make([]byte, C._goboringcrypto_BN_num_bytes(bn))
|
||||
n := C._goboringcrypto_BN_bn2bin(bn, base(raw))
|
||||
return new(big.Int).SetBytes(raw[:n])
|
||||
}
|
||||
|
||||
func bigToBn(bnp **C.GO_BIGNUM, b *big.Int) bool {
|
||||
if *bnp != nil {
|
||||
C._goboringcrypto_BN_free(*bnp)
|
||||
*bnp = nil
|
||||
}
|
||||
if b == nil {
|
||||
return true
|
||||
}
|
||||
raw := b.Bytes()
|
||||
bn := C._goboringcrypto_BN_bin2bn(base(raw), C.size_t(len(raw)), nil)
|
||||
if bn == nil {
|
||||
return false
|
||||
}
|
||||
*bnp = bn
|
||||
return true
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
// Most functionality in this package is tested by replacing existing code
|
||||
// and inheriting that code's tests.
|
||||
|
||||
package boring
|
||||
|
||||
import "testing"
|
||||
|
||||
// Test that func init does not panic.
|
||||
func TestInit(t *testing.T) {}
|
||||
|
||||
// Test that Unreachable panics.
|
||||
func TestUnreachable(t *testing.T) {
|
||||
defer func() {
|
||||
if Enabled {
|
||||
if err := recover(); err == nil {
|
||||
t.Fatal("expected Unreachable to panic")
|
||||
}
|
||||
} else {
|
||||
if err := recover(); err != nil {
|
||||
t.Fatalf("expected Unreachable to be a no-op")
|
||||
}
|
||||
}
|
||||
}()
|
||||
Unreachable()
|
||||
}
|
||||
|
||||
// Test that UnreachableExceptTests does not panic (this is a test).
|
||||
func TestUnreachableExceptTests(t *testing.T) {
|
||||
UnreachableExceptTests()
|
||||
}
|
||||
1
src/crypto/internal/boring/build/.gitignore
vendored
1
src/crypto/internal/boring/build/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
boringssl-24e5886c0edfc409c8083d10f9f1120111efd6f5.tar.xz
|
||||
@@ -1,6 +0,0 @@
|
||||
This is not a Go package. The directory must not contain Go sources,
|
||||
to prevent it from being considered a Go package.
|
||||
|
||||
This directory holds the script for building ../goboringcrypto_*.syso.
|
||||
Run build.sh on an Ubuntu system.
|
||||
See the comment at the top of build.sh for details.
|
||||
@@ -1,63 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Copyright 2017 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.
|
||||
|
||||
# Run on Ubuntu system set up with:
|
||||
# sudo apt-get install debootstrap
|
||||
# sudo apt-get install squid-deb-proxy
|
||||
#
|
||||
# The script sets up an Ubuntu chroot and then runs the build
|
||||
# in that chroot, to make sure we know exactly what software
|
||||
# is being used for the build. To repeat the script reusing the
|
||||
# chroot installation, run build.sh -quick. This mode is useful
|
||||
# if all you've modified is goboringcrypto.c and ../goboringcrypto.h
|
||||
# (or some of the setup scripts in this directory).
|
||||
|
||||
# Comment this setting out if not using squid-deb-proxy,
|
||||
# but it will be much slower to repeat the script.
|
||||
http_proxy=http://127.0.0.1:8000
|
||||
|
||||
chroot=/var/tmp/boringssl
|
||||
|
||||
sudo umount -f $chroot/proc
|
||||
sudo umount -f $chroot/sys
|
||||
sudo umount -f $chroot/dev/pts
|
||||
sudo umount -f $chroot/dev
|
||||
|
||||
set -e
|
||||
if [ "$1" != "-quick" ]; then
|
||||
sudo rm -rf $chroot
|
||||
sudo http_proxy=$http_proxy debootstrap --variant=minbase zesty $chroot
|
||||
fi
|
||||
|
||||
sudo chown $USER $chroot
|
||||
sudo chmod u+w $chroot
|
||||
|
||||
sudo mount -t proc proc $chroot/proc
|
||||
sudo mount -t sysfs sys $chroot/sys
|
||||
sudo mount -o bind /dev $chroot/dev
|
||||
sudo mount -t devpts devpts $chroot/dev/pts
|
||||
|
||||
sudo cp sources.list $chroot/etc/apt/sources.list
|
||||
|
||||
cp *chroot.sh $chroot
|
||||
|
||||
# Following http://csrc.nist.gov/groups/STM/cmvp/documents/140-1/140sp/140sp2964.pdf page 18.
|
||||
if [ ! -e $chroot/boringssl-24e5886c0edfc409c8083d10f9f1120111efd6f5.tar.xz ]; then
|
||||
wget -O $chroot/boringssl-24e5886c0edfc409c8083d10f9f1120111efd6f5.tar.xz https://commondatastorage.googleapis.com/chromium-boringssl-docs/fips/boringssl-24e5886c0edfc409c8083d10f9f1120111efd6f5.tar.xz
|
||||
fi
|
||||
if [ "$(sha256sum $chroot/boringssl-24e5886c0edfc409c8083d10f9f1120111efd6f5.tar.xz | awk '{print $1}')" != 15a65d676eeae27618e231183a1ce9804fc9c91bcc3abf5f6ca35216c02bf4da ]; then
|
||||
echo WRONG SHA256SUM
|
||||
exit 2
|
||||
fi
|
||||
|
||||
rm -rf $chroot/godriver
|
||||
mkdir $chroot/godriver
|
||||
cp ../goboringcrypto.h $chroot/godriver
|
||||
|
||||
sudo http_proxy=$http_proxy chroot $chroot /root_setup_in_chroot.sh
|
||||
sudo chroot --userspec=$(id -u):$(id -g) $chroot /build_in_chroot.sh
|
||||
cp $chroot/godriver/goboringcrypto_linux_amd64.syso ..
|
||||
sha256sum ../goboringcrypto_linux_amd64.syso
|
||||
echo DONE
|
||||
@@ -1,198 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Copyright 2017 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.
|
||||
|
||||
set -e
|
||||
echo running build_in_chroot.sh
|
||||
id
|
||||
date
|
||||
export LANG=C
|
||||
unset LANGUAGE
|
||||
|
||||
# Build BoringCrypto libcrypto.a.
|
||||
# Following http://csrc.nist.gov/groups/STM/cmvp/documents/140-1/140sp/140sp2964.pdf page 18.
|
||||
if ! [ -e ./boringssl/build/tool/bssl ]; then
|
||||
export PATH=$PATH:/usr/lib/go-1.8/bin:/clangbin
|
||||
|
||||
# Go requires -fPIC for linux/amd64 cgo builds.
|
||||
# Setting -fPIC only affects the compilation of the non-module code in libcrypto.a,
|
||||
# because the FIPS module itself is already built with -fPIC.
|
||||
mkdir /clangbin
|
||||
echo '#!/bin/bash
|
||||
exec clang-4.0 -fPIC "$@"
|
||||
' >/clangbin/clang
|
||||
echo '#!/bin/bash
|
||||
exec clang++-4.0 -fPIC "$@"
|
||||
' >/clangbin/clang++
|
||||
chmod +x /clangbin/clang /clangbin/clang++
|
||||
|
||||
rm -rf boringssl
|
||||
tar xJf ../boringssl-*z
|
||||
cd boringssl
|
||||
|
||||
# Verbatim instructions from BoringCrypto build docs.
|
||||
printf "set(CMAKE_C_COMPILER \"clang\")\nset(CMAKE_CXX_COMPILER \"clang++\")\n" >/toolchain
|
||||
mkdir build && cd build && cmake -GNinja -DCMAKE_TOOLCHAIN_FILE=/toolchain -DFIPS=1 -DCMAKE_BUILD_TYPE=Release ..
|
||||
ninja -v
|
||||
ninja run_tests
|
||||
|
||||
cd ../..
|
||||
fi
|
||||
if [ "$(./boringssl/build/tool/bssl isfips)" != 1 ]; then
|
||||
echo "NOT FIPS"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
|
||||
# Build and run test C++ program to make sure goboringcrypto.h matches openssl/*.h.
|
||||
# Also collect list of checked symbols in syms.txt
|
||||
set -x
|
||||
set -e
|
||||
cd godriver
|
||||
cat >goboringcrypto.cc <<'EOF'
|
||||
#include <cassert>
|
||||
#include "goboringcrypto0.h"
|
||||
#include "goboringcrypto1.h"
|
||||
#define check_size(t) if(sizeof(t) != sizeof(GO_ ## t)) {printf("sizeof(" #t ")=%d, but sizeof(GO_" #t ")=%d\n", (int)sizeof(t), (int)sizeof(GO_ ## t)); ret=1;}
|
||||
#define check_func(f) { auto x = f; x = _goboringcrypto_ ## f ; }
|
||||
#define check_value(n, v) if(n != v) {printf(#n "=%d, but goboringcrypto.h defines it as %d\n", (int)n, (int)v); ret=1;}
|
||||
int main() {
|
||||
int ret = 0;
|
||||
#include "goboringcrypto.x"
|
||||
return ret;
|
||||
}
|
||||
EOF
|
||||
|
||||
awk '
|
||||
BEGIN {
|
||||
exitcode = 0
|
||||
}
|
||||
|
||||
# Ignore comments, #includes, blank lines.
|
||||
/^\/\// || /^#/ || NF == 0 { next }
|
||||
|
||||
# Ignore unchecked declarations.
|
||||
/\/\*unchecked/ { next }
|
||||
|
||||
# Check enum values.
|
||||
!enum && $1 == "enum" && $NF == "{" {
|
||||
enum = 1
|
||||
next
|
||||
}
|
||||
enum && $1 == "};" {
|
||||
enum = 0
|
||||
next
|
||||
}
|
||||
enum && NF == 3 && $2 == "=" {
|
||||
name = $1
|
||||
sub(/^GO_/, "", name)
|
||||
val = $3
|
||||
sub(/,$/, "", val)
|
||||
print "check_value(" name ", " val ")" > "goboringcrypto.x"
|
||||
next
|
||||
}
|
||||
enum {
|
||||
print FILENAME ":" NR ": unexpected line in enum: " $0 > "/dev/stderr"
|
||||
exitcode = 1
|
||||
next
|
||||
}
|
||||
|
||||
# Check struct sizes.
|
||||
/^typedef struct / && $NF ~ /^GO_/ {
|
||||
name = $NF
|
||||
sub(/^GO_/, "", name)
|
||||
sub(/;$/, "", name)
|
||||
print "check_size(" name ")" > "goboringcrypto.x"
|
||||
next
|
||||
}
|
||||
|
||||
# Check function prototypes.
|
||||
/^(const )?[^ ]+ \**_goboringcrypto_.*\(/ {
|
||||
name = $2
|
||||
if($1 == "const")
|
||||
name = $3
|
||||
sub(/^\**_goboringcrypto_/, "", name)
|
||||
sub(/\(.*/, "", name)
|
||||
print "check_func(" name ")" > "goboringcrypto.x"
|
||||
print name > "syms.txt"
|
||||
next
|
||||
}
|
||||
|
||||
{
|
||||
print FILENAME ":" NR ": unexpected line: " $0 > "/dev/stderr"
|
||||
exitcode = 1
|
||||
}
|
||||
|
||||
END {
|
||||
exit exitcode
|
||||
}
|
||||
' goboringcrypto.h
|
||||
|
||||
cat goboringcrypto.h | awk '
|
||||
/^\/\/ #include/ {sub(/\/\//, ""); print > "goboringcrypto0.h"; next}
|
||||
/typedef struct|enum ([a-z_]+ )?{|^[ \t]/ {print;next}
|
||||
{gsub(/GO_/, ""); gsub(/enum go_/, "enum "); print}
|
||||
' >goboringcrypto1.h
|
||||
clang++-4.0 -std=c++11 -fPIC -I../boringssl/include -O2 -o a.out goboringcrypto.cc
|
||||
./a.out || exit 2
|
||||
|
||||
# Prepare copy of libcrypto.a with only the checked functions renamed and exported.
|
||||
# All other symbols are left alone and hidden.
|
||||
echo BORINGSSL_bcm_power_on_self_test >>syms.txt
|
||||
awk '{print "_goboringcrypto_" $0 }' syms.txt >globals.txt
|
||||
awk '{print $0 " _goboringcrypto_" $0 }' syms.txt >renames.txt
|
||||
objcopy --globalize-symbol=BORINGSSL_bcm_power_on_self_test ../boringssl/build/crypto/libcrypto.a libcrypto.a
|
||||
|
||||
# clang implements u128 % u128 -> u128 by calling __umodti3,
|
||||
# which is in libgcc. To make the result self-contained even if linking
|
||||
# against a different compiler version, link our own __umodti3 into the syso.
|
||||
# This one is specialized so it only expects divisors below 2^64,
|
||||
# which is all BoringCrypto uses. (Otherwise it will seg fault.)
|
||||
cat >umod.s <<'EOF'
|
||||
# tu_int __umodti3(tu_int x, tu_int y)
|
||||
# x is rsi:rdi, y is rcx:rdx, return result is rdx:rax.
|
||||
.globl __umodti3
|
||||
__umodti3:
|
||||
# specialized to u128 % u64, so verify that
|
||||
test %rcx,%rcx
|
||||
jne 1f
|
||||
|
||||
# save divisor
|
||||
movq %rdx, %r8
|
||||
|
||||
# reduce top 64 bits mod divisor
|
||||
movq %rsi, %rax
|
||||
xorl %edx, %edx
|
||||
divq %r8
|
||||
|
||||
# reduce full 128-bit mod divisor
|
||||
# quotient fits in 64 bits because top 64 bits have been reduced < divisor.
|
||||
# (even though we only care about the remainder, divq also computes
|
||||
# the quotient, and it will trap if the quotient is too large.)
|
||||
movq %rdi, %rax
|
||||
divq %r8
|
||||
|
||||
# expand remainder to 128 for return
|
||||
movq %rdx, %rax
|
||||
xorl %edx, %edx
|
||||
ret
|
||||
|
||||
1:
|
||||
# crash - only want 64-bit divisor
|
||||
xorl %ecx, %ecx
|
||||
movl %ecx, 0(%ecx)
|
||||
jmp 1b
|
||||
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
EOF
|
||||
clang-4.0 -c -o umod.o umod.s
|
||||
|
||||
ld -r -nostdlib --whole-archive -o goboringcrypto.o libcrypto.a umod.o
|
||||
echo __umodti3 _goboringcrypto___umodti3 >>renames.txt
|
||||
objcopy --redefine-syms=renames.txt goboringcrypto.o goboringcrypto2.o
|
||||
objcopy --keep-global-symbols=globals.txt goboringcrypto2.o goboringcrypto_linux_amd64.syso
|
||||
|
||||
# Done!
|
||||
ls -l goboringcrypto_linux_amd64.syso
|
||||
sha256sum goboringcrypto_linux_amd64.syso
|
||||
@@ -1,13 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Copyright 2017 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.
|
||||
|
||||
set -e
|
||||
id
|
||||
date
|
||||
echo http_proxy=$http_proxy
|
||||
export LANG=C
|
||||
unset LANGUAGE
|
||||
apt-get update
|
||||
apt-get install --no-install-recommends -y cmake clang-4.0 golang-1.8-go ninja-build xz-utils
|
||||
@@ -1,10 +0,0 @@
|
||||
deb http://archive.ubuntu.com/ubuntu/ zesty main restricted
|
||||
deb http://archive.ubuntu.com/ubuntu/ zesty-updates main restricted
|
||||
deb http://archive.ubuntu.com/ubuntu/ zesty universe
|
||||
deb http://archive.ubuntu.com/ubuntu/ zesty-updates universe
|
||||
deb http://archive.ubuntu.com/ubuntu/ zesty multiverse
|
||||
deb http://archive.ubuntu.com/ubuntu/ zesty-updates multiverse
|
||||
deb http://archive.ubuntu.com/ubuntu/ zesty-backports main restricted universe multiverse
|
||||
deb http://security.ubuntu.com/ubuntu zesty-security main restricted
|
||||
deb http://security.ubuntu.com/ubuntu zesty-security universe
|
||||
deb http://security.ubuntu.com/ubuntu zesty-security multiverse
|
||||
@@ -1,14 +0,0 @@
|
||||
// Copyright 2017 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 boring provides access to BoringCrypto implementation functions.
|
||||
// Check the constant Enabled to find out whether BoringCrypto is available.
|
||||
// If BoringCrypto is not available, the functions in this package all panic.
|
||||
package boring
|
||||
|
||||
// Enabled reports whether BoringCrypto is available.
|
||||
// When enabled is false, all functions in this package panic.
|
||||
//
|
||||
// BoringCrypto is only available on linux/amd64 systems.
|
||||
const Enabled = available
|
||||
@@ -1,201 +0,0 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build linux,amd64
|
||||
// +build !android
|
||||
// +build !cmd_go_bootstrap
|
||||
// +build !msan
|
||||
|
||||
package boring
|
||||
|
||||
// #include "goboringcrypto.h"
|
||||
import "C"
|
||||
import (
|
||||
"encoding/asn1"
|
||||
"errors"
|
||||
"math/big"
|
||||
"runtime"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type ecdsaSignature struct {
|
||||
R, S *big.Int
|
||||
}
|
||||
|
||||
type PrivateKeyECDSA struct {
|
||||
key *C.GO_EC_KEY
|
||||
}
|
||||
|
||||
func (k *PrivateKeyECDSA) finalize() {
|
||||
C._goboringcrypto_EC_KEY_free(k.key)
|
||||
}
|
||||
|
||||
type PublicKeyECDSA struct {
|
||||
key *C.GO_EC_KEY
|
||||
}
|
||||
|
||||
func (k *PublicKeyECDSA) finalize() {
|
||||
C._goboringcrypto_EC_KEY_free(k.key)
|
||||
}
|
||||
|
||||
var errUnknownCurve = errors.New("boringcrypto: unknown elliptic curve")
|
||||
|
||||
func curveNID(curve string) (C.int, error) {
|
||||
switch curve {
|
||||
case "P-224":
|
||||
return C.GO_NID_secp224r1, nil
|
||||
case "P-256":
|
||||
return C.GO_NID_X9_62_prime256v1, nil
|
||||
case "P-384":
|
||||
return C.GO_NID_secp384r1, nil
|
||||
case "P-521":
|
||||
return C.GO_NID_secp521r1, nil
|
||||
}
|
||||
return 0, errUnknownCurve
|
||||
}
|
||||
|
||||
func NewPublicKeyECDSA(curve string, X, Y *big.Int) (*PublicKeyECDSA, error) {
|
||||
key, err := newECKey(curve, X, Y)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
k := &PublicKeyECDSA{key}
|
||||
// Note: Because of the finalizer, any time k.key is passed to cgo,
|
||||
// that call must be followed by a call to runtime.KeepAlive(k),
|
||||
// to make sure k is not collected (and finalized) before the cgo
|
||||
// call returns.
|
||||
runtime.SetFinalizer(k, (*PublicKeyECDSA).finalize)
|
||||
return k, nil
|
||||
}
|
||||
|
||||
func newECKey(curve string, X, Y *big.Int) (*C.GO_EC_KEY, error) {
|
||||
nid, err := curveNID(curve)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key := C._goboringcrypto_EC_KEY_new_by_curve_name(nid)
|
||||
if key == nil {
|
||||
return nil, fail("EC_KEY_new_by_curve_name")
|
||||
}
|
||||
group := C._goboringcrypto_EC_KEY_get0_group(key)
|
||||
pt := C._goboringcrypto_EC_POINT_new(group)
|
||||
if pt == nil {
|
||||
C._goboringcrypto_EC_KEY_free(key)
|
||||
return nil, fail("EC_POINT_new")
|
||||
}
|
||||
bx := bigToBN(X)
|
||||
by := bigToBN(Y)
|
||||
ok := bx != nil && by != nil && C._goboringcrypto_EC_POINT_set_affine_coordinates_GFp(group, pt, bx, by, nil) != 0 &&
|
||||
C._goboringcrypto_EC_KEY_set_public_key(key, pt) != 0
|
||||
if bx != nil {
|
||||
C._goboringcrypto_BN_free(bx)
|
||||
}
|
||||
if by != nil {
|
||||
C._goboringcrypto_BN_free(by)
|
||||
}
|
||||
C._goboringcrypto_EC_POINT_free(pt)
|
||||
if !ok {
|
||||
C._goboringcrypto_EC_KEY_free(key)
|
||||
return nil, fail("EC_POINT_set_affine_coordinates_GFp")
|
||||
}
|
||||
return key, nil
|
||||
}
|
||||
|
||||
func NewPrivateKeyECDSA(curve string, X, Y *big.Int, D *big.Int) (*PrivateKeyECDSA, error) {
|
||||
key, err := newECKey(curve, X, Y)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bd := bigToBN(D)
|
||||
ok := bd != nil && C._goboringcrypto_EC_KEY_set_private_key(key, bd) != 0
|
||||
if bd != nil {
|
||||
C._goboringcrypto_BN_free(bd)
|
||||
}
|
||||
if !ok {
|
||||
C._goboringcrypto_EC_KEY_free(key)
|
||||
return nil, fail("EC_KEY_set_private_key")
|
||||
}
|
||||
k := &PrivateKeyECDSA{key}
|
||||
// Note: Because of the finalizer, any time k.key is passed to cgo,
|
||||
// that call must be followed by a call to runtime.KeepAlive(k),
|
||||
// to make sure k is not collected (and finalized) before the cgo
|
||||
// call returns.
|
||||
runtime.SetFinalizer(k, (*PrivateKeyECDSA).finalize)
|
||||
return k, nil
|
||||
}
|
||||
|
||||
func SignECDSA(priv *PrivateKeyECDSA, hash []byte) (r, s *big.Int, err error) {
|
||||
// We could use ECDSA_do_sign instead but would need to convert
|
||||
// the resulting BIGNUMs to *big.Int form. If we're going to do a
|
||||
// conversion, converting the ASN.1 form is more convenient and
|
||||
// likely not much more expensive.
|
||||
sig, err := SignMarshalECDSA(priv, hash)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
var esig ecdsaSignature
|
||||
if _, err := asn1.Unmarshal(sig, &esig); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return esig.R, esig.S, nil
|
||||
}
|
||||
|
||||
func SignMarshalECDSA(priv *PrivateKeyECDSA, hash []byte) ([]byte, error) {
|
||||
size := C._goboringcrypto_ECDSA_size(priv.key)
|
||||
sig := make([]byte, size)
|
||||
var sigLen C.uint
|
||||
if C._goboringcrypto_ECDSA_sign(0, base(hash), C.size_t(len(hash)), (*C.uint8_t)(unsafe.Pointer(&sig[0])), &sigLen, priv.key) == 0 {
|
||||
return nil, fail("ECDSA_sign")
|
||||
}
|
||||
runtime.KeepAlive(priv)
|
||||
return sig[:sigLen], nil
|
||||
}
|
||||
|
||||
func VerifyECDSA(pub *PublicKeyECDSA, hash []byte, r, s *big.Int) bool {
|
||||
// We could use ECDSA_do_verify instead but would need to convert
|
||||
// r and s to BIGNUM form. If we're going to do a conversion, marshaling
|
||||
// to ASN.1 is more convenient and likely not much more expensive.
|
||||
sig, err := asn1.Marshal(ecdsaSignature{r, s})
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
ok := C._goboringcrypto_ECDSA_verify(0, base(hash), C.size_t(len(hash)), (*C.uint8_t)(unsafe.Pointer(&sig[0])), C.size_t(len(sig)), pub.key) != 0
|
||||
runtime.KeepAlive(pub)
|
||||
return ok
|
||||
}
|
||||
|
||||
func GenerateKeyECDSA(curve string) (X, Y, D *big.Int, err error) {
|
||||
nid, err := curveNID(curve)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
key := C._goboringcrypto_EC_KEY_new_by_curve_name(nid)
|
||||
if key == nil {
|
||||
return nil, nil, nil, fail("EC_KEY_new_by_curve_name")
|
||||
}
|
||||
defer C._goboringcrypto_EC_KEY_free(key)
|
||||
if C._goboringcrypto_EC_KEY_generate_key_fips(key) == 0 {
|
||||
return nil, nil, nil, fail("EC_KEY_generate_key_fips")
|
||||
}
|
||||
group := C._goboringcrypto_EC_KEY_get0_group(key)
|
||||
pt := C._goboringcrypto_EC_KEY_get0_public_key(key)
|
||||
bd := C._goboringcrypto_EC_KEY_get0_private_key(key)
|
||||
if pt == nil || bd == nil {
|
||||
return nil, nil, nil, fail("EC_KEY_get0_private_key")
|
||||
}
|
||||
bx := C._goboringcrypto_BN_new()
|
||||
if bx == nil {
|
||||
return nil, nil, nil, fail("BN_new")
|
||||
}
|
||||
defer C._goboringcrypto_BN_free(bx)
|
||||
by := C._goboringcrypto_BN_new()
|
||||
if by == nil {
|
||||
return nil, nil, nil, fail("BN_new")
|
||||
}
|
||||
defer C._goboringcrypto_BN_free(by)
|
||||
if C._goboringcrypto_EC_POINT_get_affine_coordinates_GFp(group, pt, bx, by, nil) == 0 {
|
||||
return nil, nil, nil, fail("EC_POINT_get_affine_coordinates_GFp")
|
||||
}
|
||||
return bnToBig(bx), bnToBig(by), bnToBig(bd), nil
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
// runtime_arg0 is declared in tls.go without a body.
|
||||
// It's provided by package runtime,
|
||||
// but the go command doesn't know that.
|
||||
// Having this assembly file keeps the go command
|
||||
// from complaining about the missing body
|
||||
// (because the implementation might be here).
|
||||
@@ -1,49 +0,0 @@
|
||||
// Copyright 2017 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 fipstls allows control over whether crypto/tls requires FIPS-approved settings.
|
||||
// This package's effects are independent of the use of the BoringCrypto implementation.
|
||||
package fipstls
|
||||
|
||||
import "sync/atomic"
|
||||
|
||||
var required uint32
|
||||
|
||||
// Force forces crypto/tls to restrict TLS configurations to FIPS-approved settings.
|
||||
// By design, this call is impossible to undo (except in tests).
|
||||
//
|
||||
// Note that this call has an effect even in programs using
|
||||
// standard crypto (that is, even when Enabled = false).
|
||||
func Force() {
|
||||
atomic.StoreUint32(&required, 1)
|
||||
}
|
||||
|
||||
// Abandon allows non-FIPS-approved settings.
|
||||
// If called from a non-test binary, it panics.
|
||||
func Abandon() {
|
||||
// Note: Not using boring.UnreachableExceptTests because we want
|
||||
// this test to happen even when boring.Enabled = false.
|
||||
name := runtime_arg0()
|
||||
// Allow _test for Go command, .test for Bazel,
|
||||
// NaClMain for NaCl (where all binaries run as NaClMain),
|
||||
// and empty string for Windows (where runtime_arg0 can't easily find the name).
|
||||
// Since this is an internal package, testing that this isn't used on the
|
||||
// other operating systems should suffice to catch any mistakes.
|
||||
if !hasSuffix(name, "_test") && !hasSuffix(name, ".test") && name != "NaClMain" && name != "" {
|
||||
panic("fipstls: invalid use of Abandon in " + name)
|
||||
}
|
||||
atomic.StoreUint32(&required, 0)
|
||||
}
|
||||
|
||||
// provided by runtime
|
||||
func runtime_arg0() string
|
||||
|
||||
func hasSuffix(s, t string) bool {
|
||||
return len(s) > len(t) && s[len(s)-len(t):] == t
|
||||
}
|
||||
|
||||
// Required reports whether FIPS-approved settings are required.
|
||||
func Required() bool {
|
||||
return atomic.LoadUint32(&required) != 0
|
||||
}
|
||||
@@ -1,236 +0,0 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
// This header file describes the BoringCrypto ABI as built for use in Go.
|
||||
// The BoringCrypto build for Go (which generates goboringcrypto_*.syso)
|
||||
// takes the standard libcrypto.a from BoringCrypto and adds the prefix
|
||||
// _goboringcrypto_ to every symbol, to avoid possible conflicts with
|
||||
// code wrapping a different BoringCrypto or OpenSSL.
|
||||
//
|
||||
// To make this header standalone (so that building Go does not require
|
||||
// having a full set of BoringCrypto headers), the struct details are not here.
|
||||
// Instead, while building the syso, we compile and run a C++ program
|
||||
// that checks that the sizes match. The program also checks (during compilation)
|
||||
// that all the function prototypes match the BoringCrypto equivalents.
|
||||
// The generation of the checking program depends on the declaration
|
||||
// forms used below (one line for most, multiline for enums).
|
||||
|
||||
#include <stdlib.h> // size_t
|
||||
#include <stdint.h> // uint8_t
|
||||
|
||||
// This symbol is hidden in BoringCrypto and marked as a constructor,
|
||||
// but cmd/link's internal linking mode doesn't handle constructors.
|
||||
// Until it does, we've exported the symbol and can call it explicitly.
|
||||
// (If using external linking mode, it will therefore be called twice,
|
||||
// once explicitly and once as a constructor, but that's OK.)
|
||||
/*unchecked*/ void _goboringcrypto_BORINGSSL_bcm_power_on_self_test(void);
|
||||
|
||||
// #include <openssl/crypto.h>
|
||||
int _goboringcrypto_FIPS_mode(void);
|
||||
|
||||
// #include <openssl/rand.h>
|
||||
int _goboringcrypto_RAND_bytes(uint8_t*, size_t);
|
||||
|
||||
// #include <openssl/nid.h>
|
||||
enum {
|
||||
GO_NID_md5_sha1 = 114,
|
||||
|
||||
GO_NID_secp224r1 = 713,
|
||||
GO_NID_X9_62_prime256v1 = 415,
|
||||
GO_NID_secp384r1 = 715,
|
||||
GO_NID_secp521r1 = 716,
|
||||
|
||||
GO_NID_sha224 = 675,
|
||||
GO_NID_sha256 = 672,
|
||||
GO_NID_sha384 = 673,
|
||||
GO_NID_sha512 = 674,
|
||||
};
|
||||
|
||||
// #include <openssl/sha.h>
|
||||
typedef struct GO_SHA_CTX { char data[96]; } GO_SHA_CTX;
|
||||
int _goboringcrypto_SHA1_Init(GO_SHA_CTX*);
|
||||
int _goboringcrypto_SHA1_Update(GO_SHA_CTX*, const void*, size_t);
|
||||
int _goboringcrypto_SHA1_Final(uint8_t*, GO_SHA_CTX*);
|
||||
|
||||
typedef struct GO_SHA256_CTX { char data[48+64]; } GO_SHA256_CTX;
|
||||
int _goboringcrypto_SHA224_Init(GO_SHA256_CTX*);
|
||||
int _goboringcrypto_SHA224_Update(GO_SHA256_CTX*, const void*, size_t);
|
||||
int _goboringcrypto_SHA224_Final(uint8_t*, GO_SHA256_CTX*);
|
||||
int _goboringcrypto_SHA256_Init(GO_SHA256_CTX*);
|
||||
int _goboringcrypto_SHA256_Update(GO_SHA256_CTX*, const void*, size_t);
|
||||
int _goboringcrypto_SHA256_Final(uint8_t*, GO_SHA256_CTX*);
|
||||
|
||||
typedef struct GO_SHA512_CTX { char data[88+128]; } GO_SHA512_CTX;
|
||||
int _goboringcrypto_SHA384_Init(GO_SHA512_CTX*);
|
||||
int _goboringcrypto_SHA384_Update(GO_SHA512_CTX*, const void*, size_t);
|
||||
int _goboringcrypto_SHA384_Final(uint8_t*, GO_SHA512_CTX*);
|
||||
int _goboringcrypto_SHA512_Init(GO_SHA512_CTX*);
|
||||
int _goboringcrypto_SHA512_Update(GO_SHA512_CTX*, const void*, size_t);
|
||||
int _goboringcrypto_SHA512_Final(uint8_t*, GO_SHA512_CTX*);
|
||||
|
||||
// #include <openssl/digest.h>
|
||||
/*unchecked (opaque)*/ typedef struct GO_EVP_MD { char data[1]; } GO_EVP_MD;
|
||||
const GO_EVP_MD* _goboringcrypto_EVP_md4(void);
|
||||
const GO_EVP_MD* _goboringcrypto_EVP_md5(void);
|
||||
const GO_EVP_MD* _goboringcrypto_EVP_md5_sha1(void);
|
||||
const GO_EVP_MD* _goboringcrypto_EVP_sha1(void);
|
||||
const GO_EVP_MD* _goboringcrypto_EVP_sha224(void);
|
||||
const GO_EVP_MD* _goboringcrypto_EVP_sha256(void);
|
||||
const GO_EVP_MD* _goboringcrypto_EVP_sha384(void);
|
||||
const GO_EVP_MD* _goboringcrypto_EVP_sha512(void);
|
||||
int _goboringcrypto_EVP_MD_type(const GO_EVP_MD*);
|
||||
size_t _goboringcrypto_EVP_MD_size(const GO_EVP_MD*);
|
||||
|
||||
// #include <openssl/hmac.h>
|
||||
typedef struct GO_HMAC_CTX { char data[104]; } GO_HMAC_CTX;
|
||||
void _goboringcrypto_HMAC_CTX_init(GO_HMAC_CTX*);
|
||||
void _goboringcrypto_HMAC_CTX_cleanup(GO_HMAC_CTX*);
|
||||
int _goboringcrypto_HMAC_Init(GO_HMAC_CTX*, const void*, int, const GO_EVP_MD*);
|
||||
int _goboringcrypto_HMAC_Update(GO_HMAC_CTX*, const uint8_t*, size_t);
|
||||
int _goboringcrypto_HMAC_Final(GO_HMAC_CTX*, uint8_t*, unsigned int*);
|
||||
size_t _goboringcrypto_HMAC_size(const GO_HMAC_CTX*);
|
||||
int _goboringcrypto_HMAC_CTX_copy_ex(GO_HMAC_CTX *dest, const GO_HMAC_CTX *src);
|
||||
|
||||
// #include <openssl/aes.h>
|
||||
typedef struct GO_AES_KEY { char data[244]; } GO_AES_KEY;
|
||||
int _goboringcrypto_AES_set_encrypt_key(const uint8_t*, unsigned int, GO_AES_KEY*);
|
||||
int _goboringcrypto_AES_set_decrypt_key(const uint8_t*, unsigned int, GO_AES_KEY*);
|
||||
void _goboringcrypto_AES_encrypt(const uint8_t*, uint8_t*, const GO_AES_KEY*);
|
||||
void _goboringcrypto_AES_decrypt(const uint8_t*, uint8_t*, const GO_AES_KEY*);
|
||||
void _goboringcrypto_AES_ctr128_encrypt(const uint8_t*, uint8_t*, size_t, const GO_AES_KEY*, uint8_t*, uint8_t*, unsigned int*);
|
||||
enum {
|
||||
GO_AES_ENCRYPT = 1,
|
||||
GO_AES_DECRYPT = 0
|
||||
};
|
||||
void _goboringcrypto_AES_cbc_encrypt(const uint8_t*, uint8_t*, size_t, const GO_AES_KEY*, uint8_t*, const int);
|
||||
|
||||
// #include <openssl/aead.h>
|
||||
/*unchecked (opaque)*/ typedef struct GO_EVP_AEAD { char data[1]; } GO_EVP_AEAD;
|
||||
/*unchecked (opaque)*/ typedef struct GO_ENGINE { char data[1]; } GO_ENGINE;
|
||||
const GO_EVP_AEAD* _goboringcrypto_EVP_aead_aes_128_gcm(void);
|
||||
const GO_EVP_AEAD* _goboringcrypto_EVP_aead_aes_256_gcm(void);
|
||||
enum {
|
||||
GO_EVP_AEAD_DEFAULT_TAG_LENGTH = 0
|
||||
};
|
||||
size_t _goboringcrypto_EVP_AEAD_key_length(const GO_EVP_AEAD*);
|
||||
size_t _goboringcrypto_EVP_AEAD_nonce_length(const GO_EVP_AEAD*);
|
||||
size_t _goboringcrypto_EVP_AEAD_max_overhead(const GO_EVP_AEAD*);
|
||||
size_t _goboringcrypto_EVP_AEAD_max_tag_len(const GO_EVP_AEAD*);
|
||||
typedef struct GO_EVP_AEAD_CTX { char data[24]; } GO_EVP_AEAD_CTX;
|
||||
void _goboringcrypto_EVP_AEAD_CTX_zero(GO_EVP_AEAD_CTX*);
|
||||
int _goboringcrypto_EVP_AEAD_CTX_init(GO_EVP_AEAD_CTX*, const GO_EVP_AEAD*, const uint8_t*, size_t, size_t, GO_ENGINE*);
|
||||
void _goboringcrypto_EVP_AEAD_CTX_cleanup(GO_EVP_AEAD_CTX*);
|
||||
int _goboringcrypto_EVP_AEAD_CTX_seal(const GO_EVP_AEAD_CTX*, uint8_t*, size_t*, size_t, const uint8_t*, size_t, const uint8_t*, size_t, const uint8_t*, size_t);
|
||||
int _goboringcrypto_EVP_AEAD_CTX_open(const GO_EVP_AEAD_CTX*, uint8_t*, size_t*, size_t, const uint8_t*, size_t, const uint8_t*, size_t, const uint8_t*, size_t);
|
||||
const GO_EVP_AEAD* _goboringcrypto_EVP_aead_aes_128_gcm_tls12(void);
|
||||
const GO_EVP_AEAD* _goboringcrypto_EVP_aead_aes_256_gcm_tls12(void);
|
||||
enum go_evp_aead_direction_t {
|
||||
go_evp_aead_open = 0,
|
||||
go_evp_aead_seal = 1
|
||||
};
|
||||
int _goboringcrypto_EVP_AEAD_CTX_init_with_direction(GO_EVP_AEAD_CTX*, const GO_EVP_AEAD*, const uint8_t*, size_t, size_t, enum go_evp_aead_direction_t);
|
||||
|
||||
// #include <openssl/bn.h>
|
||||
/*unchecked (opaque)*/ typedef struct GO_BN_CTX { char data[1]; } GO_BN_CTX;
|
||||
typedef struct GO_BIGNUM { char data[24]; } GO_BIGNUM;
|
||||
GO_BIGNUM* _goboringcrypto_BN_new(void);
|
||||
void _goboringcrypto_BN_free(GO_BIGNUM*);
|
||||
unsigned _goboringcrypto_BN_num_bits(const GO_BIGNUM*);
|
||||
unsigned _goboringcrypto_BN_num_bytes(const GO_BIGNUM*);
|
||||
int _goboringcrypto_BN_is_negative(const GO_BIGNUM*);
|
||||
GO_BIGNUM* _goboringcrypto_BN_bin2bn(const uint8_t*, size_t, GO_BIGNUM*);
|
||||
size_t _goboringcrypto_BN_bn2bin(const GO_BIGNUM*, uint8_t*);
|
||||
|
||||
// #include <openssl/ec.h>
|
||||
/*unchecked (opaque)*/ typedef struct GO_EC_GROUP { char data[1]; } GO_EC_GROUP;
|
||||
GO_EC_GROUP* _goboringcrypto_EC_GROUP_new_by_curve_name(int);
|
||||
void _goboringcrypto_EC_GROUP_free(GO_EC_GROUP*);
|
||||
|
||||
/*unchecked (opaque)*/ typedef struct GO_EC_POINT { char data[1]; } GO_EC_POINT;
|
||||
GO_EC_POINT* _goboringcrypto_EC_POINT_new(const GO_EC_GROUP*);
|
||||
void _goboringcrypto_EC_POINT_free(GO_EC_POINT*);
|
||||
int _goboringcrypto_EC_POINT_get_affine_coordinates_GFp(const GO_EC_GROUP*, const GO_EC_POINT*, GO_BIGNUM*, GO_BIGNUM*, GO_BN_CTX*);
|
||||
int _goboringcrypto_EC_POINT_set_affine_coordinates_GFp(const GO_EC_GROUP*, GO_EC_POINT*, const GO_BIGNUM*, const GO_BIGNUM*, GO_BN_CTX*);
|
||||
|
||||
// #include <openssl/ec_key.h>
|
||||
/*unchecked (opaque)*/ typedef struct GO_EC_KEY { char data[1]; } GO_EC_KEY;
|
||||
GO_EC_KEY* _goboringcrypto_EC_KEY_new(void);
|
||||
GO_EC_KEY* _goboringcrypto_EC_KEY_new_by_curve_name(int);
|
||||
void _goboringcrypto_EC_KEY_free(GO_EC_KEY*);
|
||||
const GO_EC_GROUP* _goboringcrypto_EC_KEY_get0_group(const GO_EC_KEY*);
|
||||
int _goboringcrypto_EC_KEY_generate_key_fips(GO_EC_KEY*);
|
||||
int _goboringcrypto_EC_KEY_set_private_key(GO_EC_KEY*, const GO_BIGNUM*);
|
||||
int _goboringcrypto_EC_KEY_set_public_key(GO_EC_KEY*, const GO_EC_POINT*);
|
||||
int _goboringcrypto_EC_KEY_is_opaque(const GO_EC_KEY*);
|
||||
const GO_BIGNUM* _goboringcrypto_EC_KEY_get0_private_key(const GO_EC_KEY*);
|
||||
const GO_EC_POINT* _goboringcrypto_EC_KEY_get0_public_key(const GO_EC_KEY*);
|
||||
// TODO: EC_KEY_check_fips?
|
||||
|
||||
// #include <openssl/ecdsa.h>
|
||||
typedef struct GO_ECDSA_SIG { char data[16]; } GO_ECDSA_SIG;
|
||||
GO_ECDSA_SIG* _goboringcrypto_ECDSA_SIG_new(void);
|
||||
void _goboringcrypto_ECDSA_SIG_free(GO_ECDSA_SIG*);
|
||||
GO_ECDSA_SIG* _goboringcrypto_ECDSA_do_sign(const uint8_t*, size_t, const GO_EC_KEY*);
|
||||
int _goboringcrypto_ECDSA_do_verify(const uint8_t*, size_t, const GO_ECDSA_SIG*, const GO_EC_KEY*);
|
||||
int _goboringcrypto_ECDSA_sign(int, const uint8_t*, size_t, uint8_t*, unsigned int*, const GO_EC_KEY*);
|
||||
size_t _goboringcrypto_ECDSA_size(const GO_EC_KEY*);
|
||||
int _goboringcrypto_ECDSA_verify(int, const uint8_t*, size_t, const uint8_t*, size_t, const GO_EC_KEY*);
|
||||
|
||||
// #include <openssl/rsa.h>
|
||||
|
||||
// Note: order of struct fields here is unchecked.
|
||||
typedef struct GO_RSA { void *meth; GO_BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp; char data[120]; } GO_RSA;
|
||||
/*unchecked (opaque)*/ typedef struct GO_BN_GENCB { char data[1]; } GO_BN_GENCB;
|
||||
GO_RSA* _goboringcrypto_RSA_new(void);
|
||||
void _goboringcrypto_RSA_free(GO_RSA*);
|
||||
void _goboringcrypto_RSA_get0_key(const GO_RSA*, const GO_BIGNUM **n, const GO_BIGNUM **e, const GO_BIGNUM **d);
|
||||
void _goboringcrypto_RSA_get0_factors(const GO_RSA*, const GO_BIGNUM **p, const GO_BIGNUM **q);
|
||||
void _goboringcrypto_RSA_get0_crt_params(const GO_RSA*, const GO_BIGNUM **dmp1, const GO_BIGNUM **dmp2, const GO_BIGNUM **iqmp);
|
||||
int _goboringcrypto_RSA_generate_key_ex(GO_RSA*, int, GO_BIGNUM*, GO_BN_GENCB*);
|
||||
int _goboringcrypto_RSA_generate_key_fips(GO_RSA*, int, GO_BN_GENCB*);
|
||||
enum {
|
||||
GO_RSA_PKCS1_PADDING = 1,
|
||||
GO_RSA_NO_PADDING = 3,
|
||||
GO_RSA_PKCS1_OAEP_PADDING = 4,
|
||||
GO_RSA_PKCS1_PSS_PADDING = 6,
|
||||
};
|
||||
int _goboringcrypto_RSA_encrypt(GO_RSA*, size_t *out_len, uint8_t *out, size_t max_out, const uint8_t *in, size_t in_len, int padding);
|
||||
int _goboringcrypto_RSA_decrypt(GO_RSA*, size_t *out_len, uint8_t *out, size_t max_out, const uint8_t *in, size_t in_len, int padding);
|
||||
int _goboringcrypto_RSA_sign(int hash_nid, const uint8_t* in, unsigned int in_len, uint8_t *out, unsigned int *out_len, GO_RSA*);
|
||||
int _goboringcrypto_RSA_sign_pss_mgf1(GO_RSA*, size_t *out_len, uint8_t *out, size_t max_out, const uint8_t *in, size_t in_len, const GO_EVP_MD *md, const GO_EVP_MD *mgf1_md, int salt_len);
|
||||
int _goboringcrypto_RSA_sign_raw(GO_RSA*, size_t *out_len, uint8_t *out, size_t max_out, const uint8_t *in, size_t in_len, int padding);
|
||||
int _goboringcrypto_RSA_verify(int hash_nid, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len, GO_RSA*);
|
||||
int _goboringcrypto_RSA_verify_pss_mgf1(GO_RSA*, const uint8_t *msg, size_t msg_len, const GO_EVP_MD *md, const GO_EVP_MD *mgf1_md, int salt_len, const uint8_t *sig, size_t sig_len);
|
||||
int _goboringcrypto_RSA_verify_raw(GO_RSA*, size_t *out_len, uint8_t *out, size_t max_out, const uint8_t *in, size_t in_len, int padding);
|
||||
unsigned _goboringcrypto_RSA_size(const GO_RSA*);
|
||||
int _goboringcrypto_RSA_is_opaque(const GO_RSA*);
|
||||
int _goboringcrypto_RSA_check_key(const GO_RSA*);
|
||||
int _goboringcrypto_RSA_check_fips(GO_RSA*);
|
||||
GO_RSA* _goboringcrypto_RSA_public_key_from_bytes(const uint8_t*, size_t);
|
||||
GO_RSA* _goboringcrypto_RSA_private_key_from_bytes(const uint8_t*, size_t);
|
||||
int _goboringcrypto_RSA_public_key_to_bytes(uint8_t**, size_t*, const GO_RSA*);
|
||||
int _goboringcrypto_RSA_private_key_to_bytes(uint8_t**, size_t*, const GO_RSA*);
|
||||
|
||||
// #include <openssl/evp.h>
|
||||
/*unchecked (opaque)*/ typedef struct GO_EVP_PKEY { char data[1]; } GO_EVP_PKEY;
|
||||
GO_EVP_PKEY* _goboringcrypto_EVP_PKEY_new(void);
|
||||
void _goboringcrypto_EVP_PKEY_free(GO_EVP_PKEY*);
|
||||
int _goboringcrypto_EVP_PKEY_set1_RSA(GO_EVP_PKEY*, GO_RSA*);
|
||||
|
||||
/*unchecked (opaque)*/ typedef struct GO_EVP_PKEY_CTX { char data[1]; } GO_EVP_PKEY_CTX;
|
||||
|
||||
GO_EVP_PKEY_CTX* _goboringcrypto_EVP_PKEY_CTX_new(GO_EVP_PKEY*, GO_ENGINE*);
|
||||
void _goboringcrypto_EVP_PKEY_CTX_free(GO_EVP_PKEY_CTX*);
|
||||
int _goboringcrypto_EVP_PKEY_CTX_set0_rsa_oaep_label(GO_EVP_PKEY_CTX*, uint8_t*, size_t);
|
||||
int _goboringcrypto_EVP_PKEY_CTX_set_rsa_oaep_md(GO_EVP_PKEY_CTX*, const GO_EVP_MD*);
|
||||
int _goboringcrypto_EVP_PKEY_CTX_set_rsa_padding(GO_EVP_PKEY_CTX*, int padding);
|
||||
int _goboringcrypto_EVP_PKEY_decrypt(GO_EVP_PKEY_CTX*, uint8_t*, size_t*, const uint8_t*, size_t);
|
||||
int _goboringcrypto_EVP_PKEY_encrypt(GO_EVP_PKEY_CTX*, uint8_t*, size_t*, const uint8_t*, size_t);
|
||||
int _goboringcrypto_EVP_PKEY_decrypt_init(GO_EVP_PKEY_CTX*);
|
||||
int _goboringcrypto_EVP_PKEY_encrypt_init(GO_EVP_PKEY_CTX*);
|
||||
int _goboringcrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(GO_EVP_PKEY_CTX*, const GO_EVP_MD*);
|
||||
int _goboringcrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(GO_EVP_PKEY_CTX*, int);
|
||||
int _goboringcrypto_EVP_PKEY_sign_init(GO_EVP_PKEY_CTX*);
|
||||
int _goboringcrypto_EVP_PKEY_verify_init(GO_EVP_PKEY_CTX*);
|
||||
int _goboringcrypto_EVP_PKEY_sign(GO_EVP_PKEY_CTX*, uint8_t*, size_t*, const uint8_t*, size_t);
|
||||
Binary file not shown.
@@ -1,156 +0,0 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build linux,amd64
|
||||
// +build !android
|
||||
// +build !cmd_go_bootstrap
|
||||
// +build !msan
|
||||
|
||||
package boring
|
||||
|
||||
// #include "goboringcrypto.h"
|
||||
import "C"
|
||||
import (
|
||||
"crypto"
|
||||
"hash"
|
||||
"runtime"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// hashToMD converts a hash.Hash implementation from this package
|
||||
// to a BoringCrypto *C.GO_EVP_MD.
|
||||
func hashToMD(h hash.Hash) *C.GO_EVP_MD {
|
||||
switch h.(type) {
|
||||
case *sha1Hash:
|
||||
return C._goboringcrypto_EVP_sha1()
|
||||
case *sha224Hash:
|
||||
return C._goboringcrypto_EVP_sha224()
|
||||
case *sha256Hash:
|
||||
return C._goboringcrypto_EVP_sha256()
|
||||
case *sha384Hash:
|
||||
return C._goboringcrypto_EVP_sha384()
|
||||
case *sha512Hash:
|
||||
return C._goboringcrypto_EVP_sha512()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// cryptoHashToMD converts a crypto.Hash
|
||||
// to a BoringCrypto *C.GO_EVP_MD.
|
||||
func cryptoHashToMD(ch crypto.Hash) *C.GO_EVP_MD {
|
||||
switch ch {
|
||||
case crypto.MD5:
|
||||
return C._goboringcrypto_EVP_md5()
|
||||
case crypto.MD5SHA1:
|
||||
return C._goboringcrypto_EVP_md5_sha1()
|
||||
case crypto.SHA1:
|
||||
return C._goboringcrypto_EVP_sha1()
|
||||
case crypto.SHA224:
|
||||
return C._goboringcrypto_EVP_sha224()
|
||||
case crypto.SHA256:
|
||||
return C._goboringcrypto_EVP_sha256()
|
||||
case crypto.SHA384:
|
||||
return C._goboringcrypto_EVP_sha384()
|
||||
case crypto.SHA512:
|
||||
return C._goboringcrypto_EVP_sha512()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewHMAC returns a new HMAC using BoringCrypto.
|
||||
// The function h must return a hash implemented by
|
||||
// BoringCrypto (for example, h could be boring.NewSHA256).
|
||||
// If h is not recognized, NewHMAC returns nil.
|
||||
func NewHMAC(h func() hash.Hash, key []byte) hash.Hash {
|
||||
ch := h()
|
||||
md := hashToMD(ch)
|
||||
if md == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Note: Could hash down long keys here using EVP_Digest.
|
||||
hkey := make([]byte, len(key))
|
||||
copy(hkey, key)
|
||||
hmac := &boringHMAC{
|
||||
md: md,
|
||||
size: ch.Size(),
|
||||
blockSize: ch.BlockSize(),
|
||||
key: hkey,
|
||||
}
|
||||
hmac.Reset()
|
||||
return hmac
|
||||
}
|
||||
|
||||
type boringHMAC struct {
|
||||
md *C.GO_EVP_MD
|
||||
ctx C.GO_HMAC_CTX
|
||||
ctx2 C.GO_HMAC_CTX
|
||||
size int
|
||||
blockSize int
|
||||
key []byte
|
||||
sum []byte
|
||||
needCleanup bool
|
||||
}
|
||||
|
||||
func (h *boringHMAC) Reset() {
|
||||
if h.needCleanup {
|
||||
C._goboringcrypto_HMAC_CTX_cleanup(&h.ctx)
|
||||
} else {
|
||||
h.needCleanup = true
|
||||
// Note: Because of the finalizer, any time h.ctx is passed to cgo,
|
||||
// that call must be followed by a call to runtime.KeepAlive(h),
|
||||
// to make sure h is not collected (and finalized) before the cgo
|
||||
// call returns.
|
||||
runtime.SetFinalizer(h, (*boringHMAC).finalize)
|
||||
}
|
||||
C._goboringcrypto_HMAC_CTX_init(&h.ctx)
|
||||
|
||||
if C._goboringcrypto_HMAC_Init(&h.ctx, unsafe.Pointer(base(h.key)), C.int(len(h.key)), h.md) == 0 {
|
||||
panic("boringcrypto: HMAC_Init failed")
|
||||
}
|
||||
if int(C._goboringcrypto_HMAC_size(&h.ctx)) != h.size {
|
||||
println("boringcrypto: HMAC size:", C._goboringcrypto_HMAC_size(&h.ctx), "!=", h.size)
|
||||
panic("boringcrypto: HMAC size mismatch")
|
||||
}
|
||||
runtime.KeepAlive(h) // Next line will keep h alive too; just making doubly sure.
|
||||
h.sum = nil
|
||||
}
|
||||
|
||||
func (h *boringHMAC) finalize() {
|
||||
C._goboringcrypto_HMAC_CTX_cleanup(&h.ctx)
|
||||
}
|
||||
|
||||
func (h *boringHMAC) Write(p []byte) (int, error) {
|
||||
if len(p) > 0 {
|
||||
C._goboringcrypto_HMAC_Update(&h.ctx, (*C.uint8_t)(unsafe.Pointer(&p[0])), C.size_t(len(p)))
|
||||
}
|
||||
runtime.KeepAlive(h)
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func (h *boringHMAC) Size() int {
|
||||
return h.size
|
||||
}
|
||||
|
||||
func (h *boringHMAC) BlockSize() int {
|
||||
return h.blockSize
|
||||
}
|
||||
|
||||
func (h *boringHMAC) Sum(in []byte) []byte {
|
||||
if h.sum == nil {
|
||||
size := h.Size()
|
||||
h.sum = make([]byte, size)
|
||||
}
|
||||
// Make copy of context because Go hash.Hash mandates
|
||||
// that Sum has no effect on the underlying stream.
|
||||
// In particular it is OK to Sum, then Write more, then Sum again,
|
||||
// and the second Sum acts as if the first didn't happen.
|
||||
C._goboringcrypto_HMAC_CTX_init(&h.ctx2)
|
||||
if C._goboringcrypto_HMAC_CTX_copy_ex(&h.ctx2, &h.ctx) == 0 {
|
||||
panic("boringcrypto: HMAC_CTX_copy_ex failed")
|
||||
}
|
||||
C._goboringcrypto_HMAC_Final(&h.ctx2, (*C.uint8_t)(unsafe.Pointer(&h.sum[0])), nil)
|
||||
C._goboringcrypto_HMAC_CTX_cleanup(&h.ctx2)
|
||||
return append(in, h.sum...)
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !linux !amd64 !cgo android cmd_go_bootstrap msan
|
||||
|
||||
package boring
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/cipher"
|
||||
"crypto/internal/boring/sig"
|
||||
"hash"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
const available = false
|
||||
|
||||
// Unreachable marks code that should be unreachable
|
||||
// when BoringCrypto is in use. It is a no-op without BoringCrypto.
|
||||
func Unreachable() {
|
||||
// Code that's unreachable when using BoringCrypto
|
||||
// is exactly the code we want to detect for reporting
|
||||
// standard Go crypto.
|
||||
sig.StandardCrypto()
|
||||
}
|
||||
|
||||
// UnreachableExceptTests marks code that should be unreachable
|
||||
// when BoringCrypto is in use. It is a no-op without BoringCrypto.
|
||||
func UnreachableExceptTests() {}
|
||||
|
||||
type randReader int
|
||||
|
||||
func (randReader) Read(b []byte) (int, error) { panic("boringcrypto: not available") }
|
||||
|
||||
const RandReader = randReader(0)
|
||||
|
||||
func NewSHA1() hash.Hash { panic("boringcrypto: not available") }
|
||||
func NewSHA224() hash.Hash { panic("boringcrypto: not available") }
|
||||
func NewSHA256() hash.Hash { panic("boringcrypto: not available") }
|
||||
func NewSHA384() hash.Hash { panic("boringcrypto: not available") }
|
||||
func NewSHA512() hash.Hash { panic("boringcrypto: not available") }
|
||||
|
||||
func NewHMAC(h func() hash.Hash, key []byte) hash.Hash { panic("boringcrypto: not available") }
|
||||
|
||||
func NewAESCipher(key []byte) (cipher.Block, error) { panic("boringcrypto: not available") }
|
||||
|
||||
type PublicKeyECDSA struct{ _ int }
|
||||
type PrivateKeyECDSA struct{ _ int }
|
||||
|
||||
func GenerateKeyECDSA(curve string) (X, Y, D *big.Int, err error) {
|
||||
panic("boringcrypto: not available")
|
||||
}
|
||||
func NewPrivateKeyECDSA(curve string, X, Y, D *big.Int) (*PrivateKeyECDSA, error) {
|
||||
panic("boringcrypto: not available")
|
||||
}
|
||||
func NewPublicKeyECDSA(curve string, X, Y *big.Int) (*PublicKeyECDSA, error) {
|
||||
panic("boringcrypto: not available")
|
||||
}
|
||||
func SignECDSA(priv *PrivateKeyECDSA, hash []byte) (r, s *big.Int, err error) {
|
||||
panic("boringcrypto: not available")
|
||||
}
|
||||
func SignMarshalECDSA(priv *PrivateKeyECDSA, hash []byte) ([]byte, error) {
|
||||
panic("boringcrypto: not available")
|
||||
}
|
||||
func VerifyECDSA(pub *PublicKeyECDSA, hash []byte, r, s *big.Int) bool {
|
||||
panic("boringcrypto: not available")
|
||||
}
|
||||
|
||||
type PublicKeyRSA struct{ _ int }
|
||||
type PrivateKeyRSA struct{ _ int }
|
||||
|
||||
func DecryptRSAOAEP(h hash.Hash, priv *PrivateKeyRSA, ciphertext, label []byte) ([]byte, error) {
|
||||
panic("boringcrypto: not available")
|
||||
}
|
||||
func DecryptRSAPKCS1(priv *PrivateKeyRSA, ciphertext []byte) ([]byte, error) {
|
||||
panic("boringcrypto: not available")
|
||||
}
|
||||
func DecryptRSANoPadding(priv *PrivateKeyRSA, ciphertext []byte) ([]byte, error) {
|
||||
panic("boringcrypto: not available")
|
||||
}
|
||||
func EncryptRSAOAEP(h hash.Hash, pub *PublicKeyRSA, msg, label []byte) ([]byte, error) {
|
||||
panic("boringcrypto: not available")
|
||||
}
|
||||
func EncryptRSAPKCS1(pub *PublicKeyRSA, msg []byte) ([]byte, error) {
|
||||
panic("boringcrypto: not available")
|
||||
}
|
||||
func EncryptRSANoPadding(pub *PublicKeyRSA, msg []byte) ([]byte, error) {
|
||||
panic("boringcrypto: not available")
|
||||
}
|
||||
func GenerateKeyRSA(bits int) (N, E, D, P, Q, Dp, Dq, Qinv *big.Int, err error) {
|
||||
panic("boringcrypto: not available")
|
||||
}
|
||||
func NewPrivateKeyRSA(N, E, D, P, Q, Dp, Dq, Qinv *big.Int) (*PrivateKeyRSA, error) {
|
||||
panic("boringcrypto: not available")
|
||||
}
|
||||
func NewPublicKeyRSA(N, E *big.Int) (*PublicKeyRSA, error) { panic("boringcrypto: not available") }
|
||||
func SignRSAPKCS1v15(priv *PrivateKeyRSA, h crypto.Hash, hashed []byte) ([]byte, error) {
|
||||
panic("boringcrypto: not available")
|
||||
}
|
||||
func SignRSAPSS(priv *PrivateKeyRSA, h crypto.Hash, hashed []byte, saltLen int) ([]byte, error) {
|
||||
panic("boringcrypto: not available")
|
||||
}
|
||||
func VerifyRSAPKCS1v15(pub *PublicKeyRSA, h crypto.Hash, hashed, sig []byte) error {
|
||||
panic("boringcrypto: not available")
|
||||
}
|
||||
func VerifyRSAPSS(pub *PublicKeyRSA, h crypto.Hash, hashed, sig []byte, saltLen int) error {
|
||||
panic("boringcrypto: not available")
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build linux,amd64
|
||||
// +build !android
|
||||
// +build !cmd_go_bootstrap
|
||||
// +build !msan
|
||||
|
||||
package boring
|
||||
|
||||
// #include "goboringcrypto.h"
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
type randReader int
|
||||
|
||||
func (randReader) Read(b []byte) (int, error) {
|
||||
// Note: RAND_bytes should never fail; the return value exists only for historical reasons.
|
||||
// We check it even so.
|
||||
if len(b) > 0 && C._goboringcrypto_RAND_bytes((*C.uint8_t)(unsafe.Pointer(&b[0])), C.size_t(len(b))) == 0 {
|
||||
return 0, fail("RAND_bytes")
|
||||
}
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
const RandReader = randReader(0)
|
||||
@@ -1,329 +0,0 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build linux,amd64
|
||||
// +build !android
|
||||
// +build !cmd_go_bootstrap
|
||||
// +build !msan
|
||||
|
||||
package boring
|
||||
|
||||
// #include "goboringcrypto.h"
|
||||
import "C"
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/subtle"
|
||||
"errors"
|
||||
"hash"
|
||||
"math/big"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func GenerateKeyRSA(bits int) (N, E, D, P, Q, Dp, Dq, Qinv *big.Int, err error) {
|
||||
bad := func(e error) (N, E, D, P, Q, Dp, Dq, Qinv *big.Int, err error) {
|
||||
return nil, nil, nil, nil, nil, nil, nil, nil, e
|
||||
}
|
||||
|
||||
key := C._goboringcrypto_RSA_new()
|
||||
if key == nil {
|
||||
return bad(fail("RSA_new"))
|
||||
}
|
||||
defer C._goboringcrypto_RSA_free(key)
|
||||
|
||||
if C._goboringcrypto_RSA_generate_key_fips(key, C.int(bits), nil) == 0 {
|
||||
return bad(fail("RSA_generate_key_fips"))
|
||||
}
|
||||
|
||||
var n, e, d, p, q, dp, dq, qinv *C.GO_BIGNUM
|
||||
C._goboringcrypto_RSA_get0_key(key, &n, &e, &d)
|
||||
C._goboringcrypto_RSA_get0_factors(key, &p, &q)
|
||||
C._goboringcrypto_RSA_get0_crt_params(key, &dp, &dq, &qinv)
|
||||
return bnToBig(n), bnToBig(e), bnToBig(d), bnToBig(p), bnToBig(q), bnToBig(dp), bnToBig(dq), bnToBig(qinv), nil
|
||||
}
|
||||
|
||||
type PublicKeyRSA struct {
|
||||
key *C.GO_RSA
|
||||
}
|
||||
|
||||
func NewPublicKeyRSA(N, E *big.Int) (*PublicKeyRSA, error) {
|
||||
key := C._goboringcrypto_RSA_new()
|
||||
if key == nil {
|
||||
return nil, fail("RSA_new")
|
||||
}
|
||||
if !bigToBn(&key.n, N) ||
|
||||
!bigToBn(&key.e, E) {
|
||||
return nil, fail("BN_bin2bn")
|
||||
}
|
||||
k := &PublicKeyRSA{key: key}
|
||||
// Note: Because of the finalizer, any time k.key is passed to cgo,
|
||||
// that call must be followed by a call to runtime.KeepAlive(k),
|
||||
// to make sure k is not collected (and finalized) before the cgo
|
||||
// call returns.
|
||||
runtime.SetFinalizer(k, (*PublicKeyRSA).finalize)
|
||||
return k, nil
|
||||
}
|
||||
|
||||
func (k *PublicKeyRSA) finalize() {
|
||||
C._goboringcrypto_RSA_free(k.key)
|
||||
}
|
||||
|
||||
type PrivateKeyRSA struct {
|
||||
key *C.GO_RSA
|
||||
}
|
||||
|
||||
func NewPrivateKeyRSA(N, E, D, P, Q, Dp, Dq, Qinv *big.Int) (*PrivateKeyRSA, error) {
|
||||
key := C._goboringcrypto_RSA_new()
|
||||
if key == nil {
|
||||
return nil, fail("RSA_new")
|
||||
}
|
||||
if !bigToBn(&key.n, N) ||
|
||||
!bigToBn(&key.e, E) ||
|
||||
!bigToBn(&key.d, D) ||
|
||||
!bigToBn(&key.p, P) ||
|
||||
!bigToBn(&key.q, Q) ||
|
||||
!bigToBn(&key.dmp1, Dp) ||
|
||||
!bigToBn(&key.dmq1, Dq) ||
|
||||
!bigToBn(&key.iqmp, Qinv) {
|
||||
return nil, fail("BN_bin2bn")
|
||||
}
|
||||
k := &PrivateKeyRSA{key: key}
|
||||
// Note: Because of the finalizer, any time k.key is passed to cgo,
|
||||
// that call must be followed by a call to runtime.KeepAlive(k),
|
||||
// to make sure k is not collected (and finalized) before the cgo
|
||||
// call returns.
|
||||
runtime.SetFinalizer(k, (*PrivateKeyRSA).finalize)
|
||||
return k, nil
|
||||
}
|
||||
|
||||
func (k *PrivateKeyRSA) finalize() {
|
||||
C._goboringcrypto_RSA_free(k.key)
|
||||
}
|
||||
|
||||
func setupRSA(key *C.GO_RSA,
|
||||
padding C.int, h hash.Hash, label []byte, saltLen int, ch crypto.Hash,
|
||||
init func(*C.GO_EVP_PKEY_CTX) C.int) (pkey *C.GO_EVP_PKEY, ctx *C.GO_EVP_PKEY_CTX, err error) {
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if pkey != nil {
|
||||
C._goboringcrypto_EVP_PKEY_free(pkey)
|
||||
pkey = nil
|
||||
}
|
||||
if ctx != nil {
|
||||
C._goboringcrypto_EVP_PKEY_CTX_free(ctx)
|
||||
ctx = nil
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
pkey = C._goboringcrypto_EVP_PKEY_new()
|
||||
if pkey == nil {
|
||||
return nil, nil, fail("EVP_PKEY_new")
|
||||
}
|
||||
if C._goboringcrypto_EVP_PKEY_set1_RSA(pkey, key) == 0 {
|
||||
return nil, nil, fail("EVP_PKEY_set1_RSA")
|
||||
}
|
||||
ctx = C._goboringcrypto_EVP_PKEY_CTX_new(pkey, nil)
|
||||
if ctx == nil {
|
||||
return nil, nil, fail("EVP_PKEY_CTX_new")
|
||||
}
|
||||
if init(ctx) == 0 {
|
||||
return nil, nil, fail("EVP_PKEY_operation_init")
|
||||
}
|
||||
if C._goboringcrypto_EVP_PKEY_CTX_set_rsa_padding(ctx, padding) == 0 {
|
||||
return nil, nil, fail("EVP_PKEY_CTX_set_rsa_padding")
|
||||
}
|
||||
if padding == C.GO_RSA_PKCS1_OAEP_PADDING {
|
||||
md := hashToMD(h)
|
||||
if md == nil {
|
||||
return nil, nil, errors.New("crypto/rsa: unsupported hash function")
|
||||
}
|
||||
if C._goboringcrypto_EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) == 0 {
|
||||
return nil, nil, fail("EVP_PKEY_set_rsa_oaep_md")
|
||||
}
|
||||
// ctx takes ownership of label, so malloc a copy for BoringCrypto to free.
|
||||
clabel := (*C.uint8_t)(C.malloc(C.size_t(len(label))))
|
||||
if clabel == nil {
|
||||
return nil, nil, fail("malloc")
|
||||
}
|
||||
copy((*[1 << 30]byte)(unsafe.Pointer(clabel))[:len(label)], label)
|
||||
if C._goboringcrypto_EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, clabel, C.size_t(len(label))) == 0 {
|
||||
return nil, nil, fail("EVP_PKEY_CTX_set0_rsa_oaep_label")
|
||||
}
|
||||
}
|
||||
if padding == C.GO_RSA_PKCS1_PSS_PADDING {
|
||||
if saltLen != 0 {
|
||||
if C._goboringcrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, C.int(saltLen)) == 0 {
|
||||
return nil, nil, fail("EVP_PKEY_set_rsa_pss_saltlen")
|
||||
}
|
||||
}
|
||||
md := cryptoHashToMD(ch)
|
||||
if md == nil {
|
||||
return nil, nil, errors.New("crypto/rsa: unsupported hash function")
|
||||
}
|
||||
if C._goboringcrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md) == 0 {
|
||||
return nil, nil, fail("EVP_PKEY_set_rsa_mgf1_md")
|
||||
}
|
||||
}
|
||||
|
||||
return pkey, ctx, nil
|
||||
}
|
||||
|
||||
func cryptRSA(gokey interface{}, key *C.GO_RSA,
|
||||
padding C.int, h hash.Hash, label []byte, saltLen int, ch crypto.Hash,
|
||||
init func(*C.GO_EVP_PKEY_CTX) C.int,
|
||||
crypt func(*C.GO_EVP_PKEY_CTX, *C.uint8_t, *C.size_t, *C.uint8_t, C.size_t) C.int,
|
||||
in []byte) ([]byte, error) {
|
||||
|
||||
pkey, ctx, err := setupRSA(key, padding, h, label, saltLen, ch, init)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer C._goboringcrypto_EVP_PKEY_free(pkey)
|
||||
defer C._goboringcrypto_EVP_PKEY_CTX_free(ctx)
|
||||
|
||||
var outLen C.size_t
|
||||
if crypt(ctx, nil, &outLen, base(in), C.size_t(len(in))) == 0 {
|
||||
return nil, fail("EVP_PKEY_decrypt/encrypt")
|
||||
}
|
||||
out := make([]byte, outLen)
|
||||
if crypt(ctx, base(out), &outLen, base(in), C.size_t(len(in))) == 0 {
|
||||
return nil, fail("EVP_PKEY_decrypt/encrypt")
|
||||
}
|
||||
runtime.KeepAlive(gokey) // keep key from being freed before now
|
||||
return out[:outLen], nil
|
||||
}
|
||||
|
||||
func DecryptRSAOAEP(h hash.Hash, priv *PrivateKeyRSA, ciphertext, label []byte) ([]byte, error) {
|
||||
return cryptRSA(priv, priv.key, C.GO_RSA_PKCS1_OAEP_PADDING, h, label, 0, 0, decryptInit, decrypt, ciphertext)
|
||||
}
|
||||
|
||||
func EncryptRSAOAEP(h hash.Hash, pub *PublicKeyRSA, msg, label []byte) ([]byte, error) {
|
||||
return cryptRSA(pub, pub.key, C.GO_RSA_PKCS1_OAEP_PADDING, h, label, 0, 0, encryptInit, encrypt, msg)
|
||||
}
|
||||
|
||||
func DecryptRSAPKCS1(priv *PrivateKeyRSA, ciphertext []byte) ([]byte, error) {
|
||||
return cryptRSA(priv, priv.key, C.GO_RSA_PKCS1_PADDING, nil, nil, 0, 0, decryptInit, decrypt, ciphertext)
|
||||
}
|
||||
|
||||
func EncryptRSAPKCS1(pub *PublicKeyRSA, msg []byte) ([]byte, error) {
|
||||
return cryptRSA(pub, pub.key, C.GO_RSA_PKCS1_PADDING, nil, nil, 0, 0, encryptInit, encrypt, msg)
|
||||
}
|
||||
|
||||
func DecryptRSANoPadding(priv *PrivateKeyRSA, ciphertext []byte) ([]byte, error) {
|
||||
return cryptRSA(priv, priv.key, C.GO_RSA_NO_PADDING, nil, nil, 0, 0, decryptInit, decrypt, ciphertext)
|
||||
}
|
||||
|
||||
func EncryptRSANoPadding(pub *PublicKeyRSA, msg []byte) ([]byte, error) {
|
||||
return cryptRSA(pub, pub.key, C.GO_RSA_NO_PADDING, nil, nil, 0, 0, encryptInit, encrypt, msg)
|
||||
}
|
||||
|
||||
// These dumb wrappers work around the fact that cgo functions cannot be used as values directly.
|
||||
|
||||
func decryptInit(ctx *C.GO_EVP_PKEY_CTX) C.int {
|
||||
return C._goboringcrypto_EVP_PKEY_decrypt_init(ctx)
|
||||
}
|
||||
|
||||
func decrypt(ctx *C.GO_EVP_PKEY_CTX, out *C.uint8_t, outLen *C.size_t, in *C.uint8_t, inLen C.size_t) C.int {
|
||||
return C._goboringcrypto_EVP_PKEY_decrypt(ctx, out, outLen, in, inLen)
|
||||
}
|
||||
|
||||
func encryptInit(ctx *C.GO_EVP_PKEY_CTX) C.int {
|
||||
return C._goboringcrypto_EVP_PKEY_encrypt_init(ctx)
|
||||
}
|
||||
|
||||
func encrypt(ctx *C.GO_EVP_PKEY_CTX, out *C.uint8_t, outLen *C.size_t, in *C.uint8_t, inLen C.size_t) C.int {
|
||||
return C._goboringcrypto_EVP_PKEY_encrypt(ctx, out, outLen, in, inLen)
|
||||
}
|
||||
|
||||
func SignRSAPSS(priv *PrivateKeyRSA, h crypto.Hash, hashed []byte, saltLen int) ([]byte, error) {
|
||||
md := cryptoHashToMD(h)
|
||||
if md == nil {
|
||||
return nil, errors.New("crypto/rsa: unsupported hash function")
|
||||
}
|
||||
if saltLen == 0 {
|
||||
saltLen = -1
|
||||
}
|
||||
out := make([]byte, C._goboringcrypto_RSA_size(priv.key))
|
||||
var outLen C.size_t
|
||||
if C._goboringcrypto_RSA_sign_pss_mgf1(priv.key, &outLen, base(out), C.size_t(len(out)), base(hashed), C.size_t(len(hashed)), md, nil, C.int(saltLen)) == 0 {
|
||||
return nil, fail("RSA_sign_pss_mgf1")
|
||||
}
|
||||
runtime.KeepAlive(priv)
|
||||
|
||||
return out[:outLen], nil
|
||||
}
|
||||
|
||||
func VerifyRSAPSS(pub *PublicKeyRSA, h crypto.Hash, hashed, sig []byte, saltLen int) error {
|
||||
md := cryptoHashToMD(h)
|
||||
if md == nil {
|
||||
return errors.New("crypto/rsa: unsupported hash function")
|
||||
}
|
||||
if saltLen == 0 {
|
||||
saltLen = -2 // auto-recover
|
||||
}
|
||||
if C._goboringcrypto_RSA_verify_pss_mgf1(pub.key, base(hashed), C.size_t(len(hashed)), md, nil, C.int(saltLen), base(sig), C.size_t(len(sig))) == 0 {
|
||||
return fail("RSA_verify_pss_mgf1")
|
||||
}
|
||||
runtime.KeepAlive(pub)
|
||||
return nil
|
||||
}
|
||||
|
||||
func SignRSAPKCS1v15(priv *PrivateKeyRSA, h crypto.Hash, hashed []byte) ([]byte, error) {
|
||||
out := make([]byte, C._goboringcrypto_RSA_size(priv.key))
|
||||
if h == 0 {
|
||||
// No hashing.
|
||||
var outLen C.size_t
|
||||
if C._goboringcrypto_RSA_sign_raw(priv.key, &outLen, base(out), C.size_t(len(out)), base(hashed), C.size_t(len(hashed)), C.GO_RSA_PKCS1_PADDING) == 0 {
|
||||
return nil, fail("RSA_sign_raw")
|
||||
}
|
||||
runtime.KeepAlive(priv)
|
||||
return out[:outLen], nil
|
||||
}
|
||||
|
||||
md := cryptoHashToMD(h)
|
||||
if md == nil {
|
||||
return nil, errors.New("crypto/rsa: unsupported hash function: " + strconv.Itoa(int(h)))
|
||||
}
|
||||
nid := C._goboringcrypto_EVP_MD_type(md)
|
||||
var outLen C.uint
|
||||
if C._goboringcrypto_RSA_sign(nid, base(hashed), C.uint(len(hashed)), base(out), &outLen, priv.key) == 0 {
|
||||
return nil, fail("RSA_sign")
|
||||
}
|
||||
runtime.KeepAlive(priv)
|
||||
return out[:outLen], nil
|
||||
}
|
||||
|
||||
func VerifyRSAPKCS1v15(pub *PublicKeyRSA, h crypto.Hash, hashed, sig []byte) error {
|
||||
size := int(C._goboringcrypto_RSA_size(pub.key))
|
||||
if len(sig) < size {
|
||||
// BoringCrypto requires sig to be same size as RSA key, so pad with leading zeros.
|
||||
zsig := make([]byte, size)
|
||||
copy(zsig[len(zsig)-len(sig):], sig)
|
||||
sig = zsig
|
||||
}
|
||||
if h == 0 {
|
||||
var outLen C.size_t
|
||||
out := make([]byte, size)
|
||||
if C._goboringcrypto_RSA_verify_raw(pub.key, &outLen, base(out), C.size_t(len(out)), base(sig), C.size_t(len(sig)), C.GO_RSA_PKCS1_PADDING) == 0 {
|
||||
return fail("RSA_verify")
|
||||
}
|
||||
if subtle.ConstantTimeCompare(hashed, out[:outLen]) != 1 {
|
||||
return fail("RSA_verify")
|
||||
}
|
||||
runtime.KeepAlive(pub)
|
||||
return nil
|
||||
}
|
||||
md := cryptoHashToMD(h)
|
||||
if md == nil {
|
||||
return errors.New("crypto/rsa: unsupported hash function")
|
||||
}
|
||||
nid := C._goboringcrypto_EVP_MD_type(md)
|
||||
if C._goboringcrypto_RSA_verify(nid, base(hashed), C.size_t(len(hashed)), base(sig), C.size_t(len(sig)), pub.key) == 0 {
|
||||
return fail("RSA_verify")
|
||||
}
|
||||
runtime.KeepAlive(pub)
|
||||
return nil
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build linux,amd64
|
||||
// +build !android
|
||||
// +build !cmd_go_bootstrap
|
||||
// +build !msan
|
||||
|
||||
package boring
|
||||
|
||||
// #include "goboringcrypto.h"
|
||||
import "C"
|
||||
import (
|
||||
"hash"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// NewSHA1 returns a new SHA1 hash.
|
||||
func NewSHA1() hash.Hash {
|
||||
h := new(sha1Hash)
|
||||
h.Reset()
|
||||
return h
|
||||
}
|
||||
|
||||
type sha1Hash struct {
|
||||
ctx C.GO_SHA_CTX
|
||||
out [20]byte
|
||||
}
|
||||
|
||||
func (h *sha1Hash) Reset() { C._goboringcrypto_SHA1_Init(&h.ctx) }
|
||||
func (h *sha1Hash) Size() int { return 20 }
|
||||
func (h *sha1Hash) BlockSize() int { return 64 }
|
||||
func (h *sha1Hash) Sum(in []byte) []byte { return append(in, h.sum()...) }
|
||||
|
||||
func (h *sha1Hash) Write(p []byte) (int, error) {
|
||||
if len(p) > 0 && C._goboringcrypto_SHA1_Update(&h.ctx, unsafe.Pointer(&p[0]), C.size_t(len(p))) == 0 {
|
||||
panic("boringcrypto: SHA1_Update failed")
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func (h0 *sha1Hash) sum() []byte {
|
||||
h := *h0 // make copy so future Write+Sum is valid
|
||||
if C._goboringcrypto_SHA1_Final((*C.uint8_t)(unsafe.Pointer(&h.out[0])), &h.ctx) == 0 {
|
||||
panic("boringcrypto: SHA1_Final failed")
|
||||
}
|
||||
return h.out[:]
|
||||
}
|
||||
|
||||
// NewSHA224 returns a new SHA224 hash.
|
||||
func NewSHA224() hash.Hash {
|
||||
h := new(sha224Hash)
|
||||
h.Reset()
|
||||
return h
|
||||
}
|
||||
|
||||
type sha224Hash struct {
|
||||
ctx C.GO_SHA256_CTX
|
||||
out [224 / 8]byte
|
||||
}
|
||||
|
||||
func (h *sha224Hash) Reset() { C._goboringcrypto_SHA224_Init(&h.ctx) }
|
||||
func (h *sha224Hash) Size() int { return 224 / 8 }
|
||||
func (h *sha224Hash) BlockSize() int { return 64 }
|
||||
func (h *sha224Hash) Sum(in []byte) []byte { return append(in, h.sum()...) }
|
||||
|
||||
func (h *sha224Hash) Write(p []byte) (int, error) {
|
||||
if len(p) > 0 && C._goboringcrypto_SHA224_Update(&h.ctx, unsafe.Pointer(&p[0]), C.size_t(len(p))) == 0 {
|
||||
panic("boringcrypto: SHA224_Update failed")
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func (h0 *sha224Hash) sum() []byte {
|
||||
h := *h0 // make copy so future Write+Sum is valid
|
||||
if C._goboringcrypto_SHA224_Final((*C.uint8_t)(unsafe.Pointer(&h.out[0])), &h.ctx) == 0 {
|
||||
panic("boringcrypto: SHA224_Final failed")
|
||||
}
|
||||
return h.out[:]
|
||||
}
|
||||
|
||||
// NewSHA256 returns a new SHA256 hash.
|
||||
func NewSHA256() hash.Hash {
|
||||
h := new(sha256Hash)
|
||||
h.Reset()
|
||||
return h
|
||||
}
|
||||
|
||||
type sha256Hash struct {
|
||||
ctx C.GO_SHA256_CTX
|
||||
out [256 / 8]byte
|
||||
}
|
||||
|
||||
func (h *sha256Hash) Reset() { C._goboringcrypto_SHA256_Init(&h.ctx) }
|
||||
func (h *sha256Hash) Size() int { return 256 / 8 }
|
||||
func (h *sha256Hash) BlockSize() int { return 64 }
|
||||
func (h *sha256Hash) Sum(in []byte) []byte { return append(in, h.sum()...) }
|
||||
|
||||
func (h *sha256Hash) Write(p []byte) (int, error) {
|
||||
if len(p) > 0 && C._goboringcrypto_SHA256_Update(&h.ctx, unsafe.Pointer(&p[0]), C.size_t(len(p))) == 0 {
|
||||
panic("boringcrypto: SHA256_Update failed")
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func (h0 *sha256Hash) sum() []byte {
|
||||
h := *h0 // make copy so future Write+Sum is valid
|
||||
if C._goboringcrypto_SHA256_Final((*C.uint8_t)(unsafe.Pointer(&h.out[0])), &h.ctx) == 0 {
|
||||
panic("boringcrypto: SHA256_Final failed")
|
||||
}
|
||||
return h.out[:]
|
||||
}
|
||||
|
||||
// NewSHA384 returns a new SHA384 hash.
|
||||
func NewSHA384() hash.Hash {
|
||||
h := new(sha384Hash)
|
||||
h.Reset()
|
||||
return h
|
||||
}
|
||||
|
||||
type sha384Hash struct {
|
||||
ctx C.GO_SHA512_CTX
|
||||
out [384 / 8]byte
|
||||
}
|
||||
|
||||
func (h *sha384Hash) Reset() { C._goboringcrypto_SHA384_Init(&h.ctx) }
|
||||
func (h *sha384Hash) Size() int { return 384 / 8 }
|
||||
func (h *sha384Hash) BlockSize() int { return 128 }
|
||||
func (h *sha384Hash) Sum(in []byte) []byte { return append(in, h.sum()...) }
|
||||
|
||||
func (h *sha384Hash) Write(p []byte) (int, error) {
|
||||
if len(p) > 0 && C._goboringcrypto_SHA384_Update(&h.ctx, unsafe.Pointer(&p[0]), C.size_t(len(p))) == 0 {
|
||||
panic("boringcrypto: SHA384_Update failed")
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func (h0 *sha384Hash) sum() []byte {
|
||||
h := *h0 // make copy so future Write+Sum is valid
|
||||
if C._goboringcrypto_SHA384_Final((*C.uint8_t)(unsafe.Pointer(&h.out[0])), &h.ctx) == 0 {
|
||||
panic("boringcrypto: SHA384_Final failed")
|
||||
}
|
||||
return h.out[:]
|
||||
}
|
||||
|
||||
// NewSHA512 returns a new SHA512 hash.
|
||||
func NewSHA512() hash.Hash {
|
||||
h := new(sha512Hash)
|
||||
h.Reset()
|
||||
return h
|
||||
}
|
||||
|
||||
type sha512Hash struct {
|
||||
ctx C.GO_SHA512_CTX
|
||||
out [512 / 8]byte
|
||||
}
|
||||
|
||||
func (h *sha512Hash) Reset() { C._goboringcrypto_SHA512_Init(&h.ctx) }
|
||||
func (h *sha512Hash) Size() int { return 512 / 8 }
|
||||
func (h *sha512Hash) BlockSize() int { return 128 }
|
||||
func (h *sha512Hash) Sum(in []byte) []byte { return append(in, h.sum()...) }
|
||||
|
||||
func (h *sha512Hash) Write(p []byte) (int, error) {
|
||||
if len(p) > 0 && C._goboringcrypto_SHA512_Update(&h.ctx, unsafe.Pointer(&p[0]), C.size_t(len(p))) == 0 {
|
||||
panic("boringcrypto: SHA512_Update failed")
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func (h0 *sha512Hash) sum() []byte {
|
||||
h := *h0 // make copy so future Write+Sum is valid
|
||||
if C._goboringcrypto_SHA512_Final((*C.uint8_t)(unsafe.Pointer(&h.out[0])), &h.ctx) == 0 {
|
||||
panic("boringcrypto: SHA512_Final failed")
|
||||
}
|
||||
return h.out[:]
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
// Copyright 2017 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 sig holds “code signatures” that can be called
|
||||
// and will result in certain code sequences being linked into
|
||||
// the final binary. The functions themselves are no-ops.
|
||||
package sig
|
||||
|
||||
// BoringCrypto indicates that the BoringCrypto module is present.
|
||||
func BoringCrypto()
|
||||
|
||||
// FIPSOnly indicates that package crypto/tls/fipsonly is present.
|
||||
func FIPSOnly()
|
||||
|
||||
// StandardCrypto indicates that standard Go crypto is present.
|
||||
func StandardCrypto()
|
||||
@@ -1,54 +0,0 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
// These functions are no-ops, but you can search for their implementations
|
||||
// to find out whether they are linked into a particular binary.
|
||||
//
|
||||
// Each function consists of a two-byte jump over the next 29-bytes,
|
||||
// then a 5-byte indicator sequence unlikely to occur in real x86 instructions,
|
||||
// then a randomly-chosen 24-byte sequence, and finally a return instruction
|
||||
// (the target of the jump).
|
||||
//
|
||||
// These sequences are known to rsc.io/goversion.
|
||||
|
||||
#define START \
|
||||
BYTE $0xEB; BYTE $0x1D; BYTE $0xF4; BYTE $0x48; BYTE $0xF4; BYTE $0x4B; BYTE $0xF4
|
||||
|
||||
#define END \
|
||||
BYTE $0xC3
|
||||
|
||||
// BoringCrypto indicates that BoringCrypto (in particular, its func init) is present.
|
||||
TEXT ·BoringCrypto(SB),NOSPLIT,$0
|
||||
START
|
||||
BYTE $0xB3; BYTE $0x32; BYTE $0xF5; BYTE $0x28;
|
||||
BYTE $0x13; BYTE $0xA3; BYTE $0xB4; BYTE $0x50;
|
||||
BYTE $0xD4; BYTE $0x41; BYTE $0xCC; BYTE $0x24;
|
||||
BYTE $0x85; BYTE $0xF0; BYTE $0x01; BYTE $0x45;
|
||||
BYTE $0x4E; BYTE $0x92; BYTE $0x10; BYTE $0x1B;
|
||||
BYTE $0x1D; BYTE $0x2F; BYTE $0x19; BYTE $0x50;
|
||||
END
|
||||
|
||||
// StandardCrypto indicates that standard Go crypto is present.
|
||||
TEXT ·StandardCrypto(SB),NOSPLIT,$0
|
||||
START
|
||||
BYTE $0xba; BYTE $0xee; BYTE $0x4d; BYTE $0xfa;
|
||||
BYTE $0x98; BYTE $0x51; BYTE $0xca; BYTE $0x56;
|
||||
BYTE $0xa9; BYTE $0x11; BYTE $0x45; BYTE $0xe8;
|
||||
BYTE $0x3e; BYTE $0x99; BYTE $0xc5; BYTE $0x9c;
|
||||
BYTE $0xf9; BYTE $0x11; BYTE $0xcb; BYTE $0x8e;
|
||||
BYTE $0x80; BYTE $0xda; BYTE $0xf1; BYTE $0x2f;
|
||||
END
|
||||
|
||||
// FIPSOnly indicates that crypto/tls/fipsonly is present.
|
||||
TEXT ·FIPSOnly(SB),NOSPLIT,$0
|
||||
START
|
||||
BYTE $0x36; BYTE $0x3C; BYTE $0xB9; BYTE $0xCE;
|
||||
BYTE $0x9D; BYTE $0x68; BYTE $0x04; BYTE $0x7D;
|
||||
BYTE $0x31; BYTE $0xF2; BYTE $0x8D; BYTE $0x32;
|
||||
BYTE $0x5D; BYTE $0x5C; BYTE $0xA5; BYTE $0x87;
|
||||
BYTE $0x3F; BYTE $0x5D; BYTE $0x80; BYTE $0xCA;
|
||||
BYTE $0xF6; BYTE $0xD6; BYTE $0x15; BYTE $0x1B;
|
||||
END
|
||||
@@ -1,19 +0,0 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
// These functions are no-ops.
|
||||
// On amd64 they have recognizable implementations, so that you can
|
||||
// search a particular binary to see if they are present.
|
||||
// On other platforms (those using this source file), they don't.
|
||||
|
||||
// +build !amd64
|
||||
|
||||
TEXT ·BoringCrypto(SB),$0
|
||||
RET
|
||||
|
||||
TEXT ·FIPSOnly(SB),$0
|
||||
RET
|
||||
|
||||
TEXT ·StandardCrypto(SB),$0
|
||||
RET
|
||||
@@ -6,19 +6,11 @@
|
||||
|
||||
package cipherhw
|
||||
|
||||
import "crypto/internal/boring"
|
||||
|
||||
// defined in asm_amd64.s
|
||||
func hasAESNI() bool
|
||||
|
||||
// AESGCMSupport returns true if the Go standard library supports AES-GCM in
|
||||
// hardware.
|
||||
func AESGCMSupport() bool {
|
||||
// If BoringCrypto is enabled, we report having
|
||||
// AES-GCM support, so that crypto/tls will
|
||||
// prioritize AES-GCM usage.
|
||||
if boring.Enabled {
|
||||
return true
|
||||
}
|
||||
return hasAESNI()
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"bufio"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/internal/boring"
|
||||
"io"
|
||||
"os"
|
||||
"runtime"
|
||||
@@ -27,10 +26,6 @@ const urandomDevice = "/dev/urandom"
|
||||
// This is sufficient on Linux, OS X, and FreeBSD.
|
||||
|
||||
func init() {
|
||||
if boring.Enabled {
|
||||
Reader = boring.RandReader
|
||||
return
|
||||
}
|
||||
if runtime.GOOS == "plan9" {
|
||||
Reader = newReader(nil)
|
||||
} else {
|
||||
@@ -50,7 +45,6 @@ type devReader struct {
|
||||
var altGetRandom func([]byte) (ok bool)
|
||||
|
||||
func (r *devReader) Read(b []byte) (n int, err error) {
|
||||
boring.Unreachable()
|
||||
if altGetRandom != nil && r.name == urandomDevice && altGetRandom(b) {
|
||||
return len(b), nil
|
||||
}
|
||||
@@ -114,7 +108,6 @@ type reader struct {
|
||||
}
|
||||
|
||||
func (r *reader) Read(b []byte) (n int, err error) {
|
||||
boring.Unreachable()
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
n = len(b)
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
// Copyright 2017 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 rsa
|
||||
|
||||
import (
|
||||
"crypto/internal/boring"
|
||||
"crypto/rand"
|
||||
"io"
|
||||
"math/big"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Cached conversions from Go PublicKey/PrivateKey to BoringCrypto.
|
||||
//
|
||||
// A new 'boring atomic.Value' field in both PublicKey and PrivateKey
|
||||
// serves as a cache for the most recent conversion. The cache is an
|
||||
// atomic.Value because code might reasonably set up a key and then
|
||||
// (thinking it immutable) use it from multiple goroutines simultaneously.
|
||||
// The first operation initializes the cache; if there are multiple simultaneous
|
||||
// first operations, they will do redundant work but not step on each other.
|
||||
//
|
||||
// We could just assume that once used in a sign/verify/encrypt/decrypt operation,
|
||||
// a particular key is never again modified, but that has not been a
|
||||
// stated assumption before. Just in case there is any existing code that
|
||||
// does modify the key between operations, we save the original values
|
||||
// alongside the cached BoringCrypto key and check that the real key
|
||||
// still matches before using the cached key. The theory is that the real
|
||||
// operations are significantly more expensive than the comparison.
|
||||
|
||||
type boringPub struct {
|
||||
key *boring.PublicKeyRSA
|
||||
orig PublicKey
|
||||
}
|
||||
|
||||
func boringPublicKey(pub *PublicKey) (*boring.PublicKeyRSA, error) {
|
||||
b := (*boringPub)(atomic.LoadPointer(&pub.boring))
|
||||
if b != nil && publicKeyEqual(&b.orig, pub) {
|
||||
return b.key, nil
|
||||
}
|
||||
|
||||
b = new(boringPub)
|
||||
b.orig = copyPublicKey(pub)
|
||||
key, err := boring.NewPublicKeyRSA(b.orig.N, big.NewInt(int64(b.orig.E)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b.key = key
|
||||
atomic.StorePointer(&pub.boring, unsafe.Pointer(b))
|
||||
return key, nil
|
||||
}
|
||||
|
||||
type boringPriv struct {
|
||||
key *boring.PrivateKeyRSA
|
||||
orig PrivateKey
|
||||
}
|
||||
|
||||
func boringPrivateKey(priv *PrivateKey) (*boring.PrivateKeyRSA, error) {
|
||||
b := (*boringPriv)(atomic.LoadPointer(&priv.boring))
|
||||
if b != nil && privateKeyEqual(&b.orig, priv) {
|
||||
return b.key, nil
|
||||
}
|
||||
|
||||
b = new(boringPriv)
|
||||
b.orig = copyPrivateKey(priv)
|
||||
|
||||
var N, E, D, P, Q, Dp, Dq, Qinv *big.Int
|
||||
N = b.orig.N
|
||||
E = big.NewInt(int64(b.orig.E))
|
||||
D = b.orig.D
|
||||
if len(b.orig.Primes) == 2 {
|
||||
P = b.orig.Primes[0]
|
||||
Q = b.orig.Primes[1]
|
||||
Dp = b.orig.Precomputed.Dp
|
||||
Dq = b.orig.Precomputed.Dq
|
||||
Qinv = b.orig.Precomputed.Qinv
|
||||
}
|
||||
key, err := boring.NewPrivateKeyRSA(N, E, D, P, Q, Dp, Dq, Qinv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b.key = key
|
||||
atomic.StorePointer(&priv.boring, unsafe.Pointer(b))
|
||||
return key, nil
|
||||
}
|
||||
|
||||
func publicKeyEqual(k1, k2 *PublicKey) bool {
|
||||
return k1.N != nil &&
|
||||
k1.N.Cmp(k2.N) == 0 &&
|
||||
k1.E == k2.E
|
||||
}
|
||||
|
||||
func copyPublicKey(k *PublicKey) PublicKey {
|
||||
return PublicKey{
|
||||
N: new(big.Int).Set(k.N),
|
||||
E: k.E,
|
||||
}
|
||||
}
|
||||
|
||||
func privateKeyEqual(k1, k2 *PrivateKey) bool {
|
||||
return publicKeyEqual(&k1.PublicKey, &k2.PublicKey) &&
|
||||
k1.D.Cmp(k2.D) == 0
|
||||
}
|
||||
|
||||
func copyPrivateKey(k *PrivateKey) PrivateKey {
|
||||
dst := PrivateKey{
|
||||
PublicKey: copyPublicKey(&k.PublicKey),
|
||||
D: new(big.Int).Set(k.D),
|
||||
}
|
||||
dst.Primes = make([]*big.Int, len(k.Primes))
|
||||
for i, p := range k.Primes {
|
||||
dst.Primes[i] = new(big.Int).Set(p)
|
||||
}
|
||||
if x := k.Precomputed.Dp; x != nil {
|
||||
dst.Precomputed.Dp = new(big.Int).Set(x)
|
||||
}
|
||||
if x := k.Precomputed.Dq; x != nil {
|
||||
dst.Precomputed.Dq = new(big.Int).Set(x)
|
||||
}
|
||||
if x := k.Precomputed.Qinv; x != nil {
|
||||
dst.Precomputed.Qinv = new(big.Int).Set(x)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// boringFakeRandomBlind consumes from random to mimic the
|
||||
// blinding operation done in the standard Go func decrypt.
|
||||
// When we are using BoringCrypto, we always let it handle decrypt
|
||||
// regardless of random source, because the blind doesn't affect
|
||||
// the visible output of decryption, but if the random source is not
|
||||
// true randomness then the caller might still observe the side effect
|
||||
// of consuming from the source. We consume from the source
|
||||
// to give the same side effect. This should only happen during tests
|
||||
// (verified by the UnreachableExceptTests call below).
|
||||
//
|
||||
// We go to the trouble of doing this so that we can verify that
|
||||
// func decrypt (standard RSA decryption) is dropped from
|
||||
// BoringCrypto-linked binaries entirely; otherwise we'd have to
|
||||
// keep it in the binary just in case a call happened with a
|
||||
// non-standard randomness source.
|
||||
func boringFakeRandomBlind(random io.Reader, priv *PrivateKey) {
|
||||
if random == nil || random == boring.RandReader {
|
||||
return
|
||||
}
|
||||
boring.UnreachableExceptTests()
|
||||
|
||||
// Copied from func decrypt.
|
||||
for {
|
||||
r, err := rand.Int(random, priv.N)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if r.Cmp(bigZero) == 0 {
|
||||
r = bigOne
|
||||
}
|
||||
_, ok := modInverse(r, priv.N)
|
||||
if ok {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,332 +0,0 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
// Note: Can run these tests against the non-BoringCrypto
|
||||
// version of the code by using "CGO_ENABLED=0 go test".
|
||||
|
||||
package rsa
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"encoding/asn1"
|
||||
"encoding/hex"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func TestBoringASN1Marshal(t *testing.T) {
|
||||
k, err := GenerateKey(rand.Reader, 128)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// This used to fail, because of the unexported 'boring' field.
|
||||
// Now the compiler hides it [sic].
|
||||
_, err = asn1.Marshal(k.PublicKey)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBoringDeepEqual(t *testing.T) {
|
||||
k, err := GenerateKey(rand.Reader, 128)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
k.boring = nil // probably nil already but just in case
|
||||
k2 := *k
|
||||
k2.boring = unsafe.Pointer(k) // anything not nil, for this test
|
||||
if !reflect.DeepEqual(k, &k2) {
|
||||
// compiler should be hiding the boring field from reflection
|
||||
t.Fatalf("DeepEqual compared boring fields")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBoringVerify(t *testing.T) {
|
||||
// This changed behavior and broke golang.org/x/crypto/openpgp.
|
||||
// Go accepts signatures without leading 0 padding, while BoringCrypto does not.
|
||||
// So the Go wrappers must adapt.
|
||||
key := &PublicKey{
|
||||
N: bigFromHex("c4fdf7b40a5477f206e6ee278eaef888ca73bf9128a9eef9f2f1ddb8b7b71a4c07cfa241f028a04edb405e4d916c61d6beabc333813dc7b484d2b3c52ee233c6a79b1eea4e9cc51596ba9cd5ac5aeb9df62d86ea051055b79d03f8a4fa9f38386f5bd17529138f3325d46801514ea9047977e0829ed728e68636802796801be1"),
|
||||
E: 65537,
|
||||
}
|
||||
|
||||
hash := fromHex("019c5571724fb5d0e47a4260c940e9803ba05a44")
|
||||
paddedHash := fromHex("3021300906052b0e03021a05000414019c5571724fb5d0e47a4260c940e9803ba05a44")
|
||||
|
||||
// signature is one byte shorter than key.N.
|
||||
sig := fromHex("5edfbeb6a73e7225ad3cc52724e2872e04260d7daf0d693c170d8c4b243b8767bc7785763533febc62ec2600c30603c433c095453ede59ff2fcabeb84ce32e0ed9d5cf15ffcbc816202b64370d4d77c1e9077d74e94a16fb4fa2e5bec23a56d7a73cf275f91691ae1801a976fcde09e981a2f6327ac27ea1fecf3185df0d56")
|
||||
|
||||
err := VerifyPKCS1v15(key, 0, paddedHash, sig)
|
||||
if err != nil {
|
||||
t.Errorf("raw: %v", err)
|
||||
}
|
||||
|
||||
err = VerifyPKCS1v15(key, crypto.SHA1, hash, sig)
|
||||
if err != nil {
|
||||
t.Errorf("sha1: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// The goal for BoringCrypto is to be indistinguishable from standard Go crypto.
|
||||
// Test that when routines are passed a not-actually-random reader, they
|
||||
// consume and potentially expose the expected bits from that reader.
|
||||
// This is awful but it makes sure that golden tests based on deterministic
|
||||
// "randomness" sources are unchanged by BoringCrypto.
|
||||
//
|
||||
// For decryption and signing, r is only used for blinding,
|
||||
// so we can and do still use BoringCrypto with its own true
|
||||
// randomness source, but we must be careful to consume
|
||||
// from r as if we'd used it for blinding.
|
||||
|
||||
type testRandReader struct {
|
||||
t *testing.T
|
||||
offset int64
|
||||
seq [8]byte
|
||||
data []byte
|
||||
buf [32]byte
|
||||
}
|
||||
|
||||
func (r *testRandReader) Read(b []byte) (int, error) {
|
||||
if len(r.data) == 0 && len(b) > 0 {
|
||||
for i := range r.seq {
|
||||
r.seq[i]++
|
||||
if r.seq[i] != 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
r.buf = sha256.Sum256(r.seq[:])
|
||||
r.data = r.buf[:]
|
||||
}
|
||||
n := copy(b, r.data)
|
||||
r.data = r.data[n:]
|
||||
r.offset += int64(n)
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (r *testRandReader) checkOffset(offset int64) {
|
||||
if r.offset != offset {
|
||||
r.t.Fatalf("r.offset = %d, expected %d", r.offset, offset)
|
||||
}
|
||||
}
|
||||
|
||||
func testRand(t *testing.T) *testRandReader {
|
||||
return &testRandReader{t: t}
|
||||
}
|
||||
|
||||
var testKeyCache struct {
|
||||
once sync.Once
|
||||
k *PrivateKey
|
||||
}
|
||||
|
||||
func testKey(t *testing.T) *PrivateKey {
|
||||
testKeyCache.once.Do(func() {
|
||||
// Note: Key must be 2048 bits in order to trigger
|
||||
// BoringCrypto code paths.
|
||||
k, err := GenerateKey(testRand(t), 2048)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
testKeyCache.k = k
|
||||
})
|
||||
return testKeyCache.k
|
||||
}
|
||||
|
||||
func bytesFromHex(t *testing.T, x string) []byte {
|
||||
b, err := hex.DecodeString(x)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func TestBoringRandGenerateKey(t *testing.T) {
|
||||
r := testRand(t)
|
||||
k, err := GenerateKey(r, 2048) // 2048 is smallest size BoringCrypto might kick in for
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
n := bigFromHex("b2e9c4c8b1c0f03ba6994fe1e715a3e598f0571f4676da420615b7b997d431ea7535ceb98e6b52172fe0d2fccfc5f696d1b34144f7d19d85633fcbf56daff805a66457b360b1b0f40ec18fb83f4c9b86f1b5fe26b209cdfff26911a95047df797210969693226423915c9be53ff1c06f86fe2d228273ef25970b90a3c70979f9d68458d5dd38f6700436f7cd5939c04be3e1f2ff52272513171540a685c9e8c8e20694e529cc3e0cc13d2fb91ac499d44b920a03e42be89a15e7ca73c29f2e2a1a8a7d9be57516ccb95e878db6ce6096e386a793cccc19eba15a37cc0f1234b7a25ee7c87569bc74c7ef3d6ad8d84a5ddb1e8901ae593f945523fe5e0ed451a5")
|
||||
if k.N.Cmp(n) != 0 {
|
||||
t.Fatalf("GenerateKey: wrong N\nhave %x\nwant %x", k.N, n)
|
||||
}
|
||||
r.checkOffset(35200)
|
||||
|
||||
// Non-Boring GenerateKey always sets CRTValues to a non-nil (possibly empty) slice.
|
||||
if k.Precomputed.CRTValues == nil {
|
||||
t.Fatalf("GenerateKey: Precomputed.CRTValues = nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBoringRandGenerateMultiPrimeKey(t *testing.T) {
|
||||
r := testRand(t)
|
||||
k, err := GenerateMultiPrimeKey(r, 2, 2048)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
n := bigFromHex("b2e9c4c8b1c0f03ba6994fe1e715a3e598f0571f4676da420615b7b997d431ea7535ceb98e6b52172fe0d2fccfc5f696d1b34144f7d19d85633fcbf56daff805a66457b360b1b0f40ec18fb83f4c9b86f1b5fe26b209cdfff26911a95047df797210969693226423915c9be53ff1c06f86fe2d228273ef25970b90a3c70979f9d68458d5dd38f6700436f7cd5939c04be3e1f2ff52272513171540a685c9e8c8e20694e529cc3e0cc13d2fb91ac499d44b920a03e42be89a15e7ca73c29f2e2a1a8a7d9be57516ccb95e878db6ce6096e386a793cccc19eba15a37cc0f1234b7a25ee7c87569bc74c7ef3d6ad8d84a5ddb1e8901ae593f945523fe5e0ed451a5")
|
||||
if k.N.Cmp(n) != 0 {
|
||||
t.Fatalf("GenerateKey: wrong N\nhave %x\nwant %x", k.N, n)
|
||||
}
|
||||
r.checkOffset(35200)
|
||||
}
|
||||
|
||||
func TestBoringRandEncryptPKCS1v15(t *testing.T) {
|
||||
r := testRand(t)
|
||||
k := testKey(t)
|
||||
enc, err := EncryptPKCS1v15(r, &k.PublicKey, []byte("hello world"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := bytesFromHex(t, "a8c8c0d248e669942a140c1184e1112afbf794b7427d9ac966bd2dbb4c05a2fee76f311f7feec743b8a8715e34bf741b0d0c4226559daf4de258ff712178e3f25fecb7d3eee90251e8ae4b4b7b907cd2763948cc9da34ce83c69934b523830545a536c1ba4d3740f4687e877acee9c768bcd8e88d472ba5d905493121f4830d95dcea36ef0f1223ffb0a9008eddfc53aca36877328924a2c631dce4b67e745564301fe51ab2c768b39e525bda1e1a08e029b58c53a0b92285f734592d2deebda957bcfd29c697aee263fce5c5023c7d3495b6a9114a8ac691aa661721cf45973b68678bb1e15d6605b9040951163d5b6df0d7f0b20dcefa251a7a8947a090f4b")
|
||||
if !bytes.Equal(enc, want) {
|
||||
t.Fatalf("EncryptPKCS1v15: wrong enc\nhave %x\nwant %x", enc, want)
|
||||
}
|
||||
r.checkOffset(242)
|
||||
}
|
||||
|
||||
func TestBoringRandDecryptPKCS1v15(t *testing.T) {
|
||||
r := testRand(t)
|
||||
k := testKey(t)
|
||||
enc := bytesFromHex(t, "a8c8c0d248e669942a140c1184e1112afbf794b7427d9ac966bd2dbb4c05a2fee76f311f7feec743b8a8715e34bf741b0d0c4226559daf4de258ff712178e3f25fecb7d3eee90251e8ae4b4b7b907cd2763948cc9da34ce83c69934b523830545a536c1ba4d3740f4687e877acee9c768bcd8e88d472ba5d905493121f4830d95dcea36ef0f1223ffb0a9008eddfc53aca36877328924a2c631dce4b67e745564301fe51ab2c768b39e525bda1e1a08e029b58c53a0b92285f734592d2deebda957bcfd29c697aee263fce5c5023c7d3495b6a9114a8ac691aa661721cf45973b68678bb1e15d6605b9040951163d5b6df0d7f0b20dcefa251a7a8947a090f4b")
|
||||
dec, err := DecryptPKCS1v15(r, k, enc)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := []byte("hello world")
|
||||
if !bytes.Equal(dec, want) {
|
||||
t.Fatalf("DecryptPKCS1v15: wrong dec\nhave %x\nwant %x", dec, want)
|
||||
}
|
||||
r.checkOffset(256)
|
||||
}
|
||||
|
||||
func TestBoringRandDecryptPKCS1v15SessionKey(t *testing.T) {
|
||||
r := testRand(t)
|
||||
k := testKey(t)
|
||||
enc := bytesFromHex(t, "a8c8c0d248e669942a140c1184e1112afbf794b7427d9ac966bd2dbb4c05a2fee76f311f7feec743b8a8715e34bf741b0d0c4226559daf4de258ff712178e3f25fecb7d3eee90251e8ae4b4b7b907cd2763948cc9da34ce83c69934b523830545a536c1ba4d3740f4687e877acee9c768bcd8e88d472ba5d905493121f4830d95dcea36ef0f1223ffb0a9008eddfc53aca36877328924a2c631dce4b67e745564301fe51ab2c768b39e525bda1e1a08e029b58c53a0b92285f734592d2deebda957bcfd29c697aee263fce5c5023c7d3495b6a9114a8ac691aa661721cf45973b68678bb1e15d6605b9040951163d5b6df0d7f0b20dcefa251a7a8947a090f4b")
|
||||
dec := make([]byte, 11)
|
||||
err := DecryptPKCS1v15SessionKey(r, k, enc, dec)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := []byte("hello world")
|
||||
if !bytes.Equal(dec, want) {
|
||||
t.Fatalf("DecryptPKCS1v15SessionKey: wrong dec\nhave %x\nwant %x", dec, want)
|
||||
}
|
||||
r.checkOffset(256)
|
||||
}
|
||||
|
||||
func TestBoringRandSignPKCS1v15(t *testing.T) {
|
||||
r := testRand(t)
|
||||
k := testKey(t)
|
||||
sum := sha1.Sum([]byte("hello"))
|
||||
sig, err := SignPKCS1v15(r, k, crypto.SHA1, sum[:])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := bytesFromHex(t, "4a8da3c0c41af2b8a93d011d4e11f4da9b2d52641c6c3d78d863987e857295adcedfae0e0d3ec00352bd134dc3fbb93b23a1fbe3718775762d78165bbbd37c6ef8e07bfa44e16ed2f1b05ebc04ba7bd60162d8689edb8709349e06bc281d34c2a3ee75d3454bfd95053cbb27c10515fb9132290a6ecc858e0c003201a9e100aac7f66af967364a1176e4ed9ef672d41481c59580f98bb82f205f712153fd5e3035a811da9d6e56e50609d1d604857f6d8e958bb84f354cfa28e0b8bcbb1261f929382d431454f07cbf60c18ff1243b11c6b552f3a0aa7e936f45cded40688ee53b1b630f944139f4f51baae49cd039b57b2b82f58f5589335137f4b09bd315f5")
|
||||
if !bytes.Equal(sig, want) {
|
||||
t.Fatalf("SignPKCS1v15(hash=SHA1): wrong sig\nhave %x\nwant %x", sig, want)
|
||||
}
|
||||
|
||||
sig, err = SignPKCS1v15(r, k, 0, sum[:])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want = bytesFromHex(t, "5d3d34495ffade926adab2de0545aaf1f22a03def949b69e1c91d34a2f0c7f2d682af46034151a1b67aa22cb9c1a8cc24c1358fce9ac6a2141879bbe107371b14faa97b12494260d9602ed1355f22ab3495b0bb7c137bc6801c1113fc2bdc00d4c250bbd8fa17e4ff86f71544b30a78e9d62c0b949afd1159760282c2700ec8be24cd884efd585ec55b45506d90e66cc3c5911baaea961e6c4e8018c4b4feb04afdd71880e3d8eff120288e53289a1bfb9fe7a3b9aca1d4549f133063647bfd4c6f4c0f4038f1bbcb4d112aa601f1b15402595076adfdbefb1bb64d3193bafb0305145bb536cd949a03ebe0470c6a155369f784afab2e25e9d5c03d8e13dcf1a")
|
||||
if !bytes.Equal(sig, want) {
|
||||
t.Fatalf("SignPKCS1v15(hash=0): wrong sig\nhave %x\nwant %x", sig, want)
|
||||
}
|
||||
r.checkOffset(768)
|
||||
}
|
||||
|
||||
func TestBoringRandSignPSS(t *testing.T) {
|
||||
r := testRand(t)
|
||||
k := testKey(t)
|
||||
sum := sha1.Sum([]byte("hello"))
|
||||
sig, err := SignPSS(r, k, crypto.SHA1, sum[:], nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := bytesFromHex(t, "a0de84c9654c2e78e33c899090f8dc0590046fda4ee29d133340800596401ae0df61bf8aa5689df3f873ad13cf55df5209c3a8c6450918b74c2017f87c2d588809740622c7752e3153a26d04bd3e9d9f6daa676e8e5e65a8a11d4fbd271d4693ab6a303652328dc1c923b484fa179fd6d9e8b523da74f3a307531c0dd75f243a041f7df22414dfdb83b3a241fe73e7af0f95cb6b60831bdd46dc05618e5cb3653476eb7d5405fa5ca98dad8f787ca86179055f305daa87eb424671878a93965e47d3002e2774be311d696b42e5691eddb2f788cd35246b408eb5d045c891ba1d57ce4c6fc935ceec90f7999406252f6266957cce4e7f12cf0ec94af358aeefa7")
|
||||
if !bytes.Equal(sig, want) {
|
||||
t.Fatalf("SignPSS: wrong sig\nhave %x\nwant %x", sig, want)
|
||||
}
|
||||
r.checkOffset(490)
|
||||
}
|
||||
|
||||
func TestBoringRandEncryptOAEP(t *testing.T) {
|
||||
r := testRand(t)
|
||||
k := testKey(t)
|
||||
enc, err := EncryptOAEP(sha256.New(), r, &k.PublicKey, []byte("hello"), []byte("label"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := bytesFromHex(t, "55dc7b590a511c2d249232ecbb70040e8e0ec03206caae5ec0a401a0ad8013209ef546870f93d0946b9845ace092d456d092403f76f12ee65c2b8759731a25589d8a7e857407d09cfbe36ae36fc4daeb514ac597b1de2f7dc8450ab78a9e420c9b5dbbae3e402c8f378bd35505a47d556b705ab8985707a22e3583c172ef5730f05fd0845880d67c1ddd3c1525aa4c2c4e162bd6435a485609f6bd76c8ff73a7b5d043e4724458594703245fabdb479ef2786c757b35932a645399f2703647785b59b971970e6bccef3e6cd6fae39f9f135203eb104f0db20cf48e461cb7d824889c0d5d6a47cd0bf213c2f7acb3ddbd3effefebb4f60458ffc8b6ff1e4cc447")
|
||||
if !bytes.Equal(enc, want) {
|
||||
t.Fatalf("EncryptOAEP: wrong enc\nhave %x\nwant %x", enc, want)
|
||||
}
|
||||
r.checkOffset(32)
|
||||
}
|
||||
|
||||
func TestBoringRandDecryptOAEP(t *testing.T) {
|
||||
r := testRand(t)
|
||||
k := testKey(t)
|
||||
enc := bytesFromHex(t, "55dc7b590a511c2d249232ecbb70040e8e0ec03206caae5ec0a401a0ad8013209ef546870f93d0946b9845ace092d456d092403f76f12ee65c2b8759731a25589d8a7e857407d09cfbe36ae36fc4daeb514ac597b1de2f7dc8450ab78a9e420c9b5dbbae3e402c8f378bd35505a47d556b705ab8985707a22e3583c172ef5730f05fd0845880d67c1ddd3c1525aa4c2c4e162bd6435a485609f6bd76c8ff73a7b5d043e4724458594703245fabdb479ef2786c757b35932a645399f2703647785b59b971970e6bccef3e6cd6fae39f9f135203eb104f0db20cf48e461cb7d824889c0d5d6a47cd0bf213c2f7acb3ddbd3effefebb4f60458ffc8b6ff1e4cc447")
|
||||
dec, err := DecryptOAEP(sha256.New(), r, k, enc, []byte("label"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := []byte("hello")
|
||||
if !bytes.Equal(dec, want) {
|
||||
t.Fatalf("DecryptOAEP: wrong dec\nhave %x\nwant %x", dec, want)
|
||||
}
|
||||
r.checkOffset(256)
|
||||
}
|
||||
|
||||
func TestBoringFinalizers(t *testing.T) {
|
||||
if runtime.GOOS == "nacl" {
|
||||
// Times out on nacl (without BoringCrypto)
|
||||
// but not clear why - probably consuming rand.Reader too quickly
|
||||
// and being throttled. Also doesn't really matter.
|
||||
t.Skip("skipping on nacl")
|
||||
}
|
||||
|
||||
k := testKey(t)
|
||||
|
||||
// Run test with GOGC=10, to make bug more likely.
|
||||
// Without the KeepAlives, the loop usually dies after
|
||||
// about 30 iterations.
|
||||
defer debug.SetGCPercent(debug.SetGCPercent(10))
|
||||
for n := 0; n < 200; n++ {
|
||||
// Clear the underlying BoringCrypto object.
|
||||
atomic.StorePointer(&k.boring, nil)
|
||||
|
||||
// Race to create the underlying BoringCrypto object.
|
||||
// The ones that lose the race are prime candidates for
|
||||
// being GC'ed too early if the finalizers are not being
|
||||
// used correctly.
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < 10; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
sum := make([]byte, 32)
|
||||
_, err := SignPKCS1v15(rand.Reader, k, crypto.SHA256, sum)
|
||||
if err != nil {
|
||||
panic(err) // usually caused by memory corruption, so hard stop
|
||||
}
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@ package rsa
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/internal/boring"
|
||||
"crypto/subtle"
|
||||
"errors"
|
||||
"io"
|
||||
@@ -35,7 +34,7 @@ type PKCS1v15DecryptOptions struct {
|
||||
//
|
||||
// WARNING: use of this function to encrypt plaintexts other than
|
||||
// session keys is dangerous. Use RSA OAEP in new protocols.
|
||||
func EncryptPKCS1v15(random io.Reader, pub *PublicKey, msg []byte) ([]byte, error) {
|
||||
func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) ([]byte, error) {
|
||||
if err := checkPub(pub); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -44,37 +43,20 @@ func EncryptPKCS1v15(random io.Reader, pub *PublicKey, msg []byte) ([]byte, erro
|
||||
return nil, ErrMessageTooLong
|
||||
}
|
||||
|
||||
if boring.Enabled && random == boring.RandReader {
|
||||
bkey, err := boringPublicKey(pub)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return boring.EncryptRSAPKCS1(bkey, msg)
|
||||
}
|
||||
boring.UnreachableExceptTests()
|
||||
|
||||
// EM = 0x00 || 0x02 || PS || 0x00 || M
|
||||
em := make([]byte, k)
|
||||
em[1] = 2
|
||||
ps, mm := em[2:len(em)-len(msg)-1], em[len(em)-len(msg):]
|
||||
err := nonZeroRandomBytes(ps, random)
|
||||
err := nonZeroRandomBytes(ps, rand)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
em[len(em)-len(msg)-1] = 0
|
||||
copy(mm, msg)
|
||||
|
||||
if boring.Enabled {
|
||||
var bkey *boring.PublicKeyRSA
|
||||
bkey, err = boringPublicKey(pub)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return boring.EncryptRSANoPadding(bkey, em)
|
||||
}
|
||||
|
||||
m := new(big.Int).SetBytes(em)
|
||||
c := encrypt(new(big.Int), pub, m)
|
||||
|
||||
copyWithLeftPad(em, c.Bytes())
|
||||
return em, nil
|
||||
}
|
||||
@@ -91,20 +73,6 @@ func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) ([]byt
|
||||
if err := checkPub(&priv.PublicKey); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if boring.Enabled {
|
||||
boringFakeRandomBlind(rand, priv)
|
||||
bkey, err := boringPrivateKey(priv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := boring.DecryptRSAPKCS1(bkey, ciphertext)
|
||||
if err != nil {
|
||||
return nil, ErrDecryption
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
valid, out, index, err := decryptPKCS1v15(rand, priv, ciphertext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -172,27 +140,13 @@ func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid
|
||||
return
|
||||
}
|
||||
|
||||
if boring.Enabled {
|
||||
boringFakeRandomBlind(rand, priv)
|
||||
var bkey *boring.PrivateKeyRSA
|
||||
bkey, err = boringPrivateKey(priv)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
em, err = boring.DecryptRSANoPadding(bkey, ciphertext)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
c := new(big.Int).SetBytes(ciphertext)
|
||||
var m *big.Int
|
||||
m, err = decrypt(rand, priv, c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
em = leftPad(m.Bytes(), k)
|
||||
c := new(big.Int).SetBytes(ciphertext)
|
||||
m, err := decrypt(rand, priv, c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
em = leftPad(m.Bytes(), k)
|
||||
firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0)
|
||||
secondByteIsTwo := subtle.ConstantTimeByteEq(em[1], 2)
|
||||
|
||||
@@ -271,7 +225,7 @@ var hashPrefixes = map[crypto.Hash][]byte{
|
||||
// messages is small, an attacker may be able to build a map from
|
||||
// messages to signatures and identify the signed messages. As ever,
|
||||
// signatures provide authenticity, not confidentiality.
|
||||
func SignPKCS1v15(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error) {
|
||||
func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error) {
|
||||
hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -283,15 +237,6 @@ func SignPKCS1v15(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed [
|
||||
return nil, ErrMessageTooLong
|
||||
}
|
||||
|
||||
if boring.Enabled {
|
||||
boringFakeRandomBlind(random, priv)
|
||||
bkey, err := boringPrivateKey(priv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return boring.SignRSAPKCS1v15(bkey, hash, hashed)
|
||||
}
|
||||
|
||||
// EM = 0x00 || 0x01 || PS || 0x00 || T
|
||||
em := make([]byte, k)
|
||||
em[1] = 1
|
||||
@@ -302,7 +247,7 @@ func SignPKCS1v15(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed [
|
||||
copy(em[k-hashLen:k], hashed)
|
||||
|
||||
m := new(big.Int).SetBytes(em)
|
||||
c, err := decryptAndCheck(random, priv, m)
|
||||
c, err := decryptAndCheck(rand, priv, m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -317,17 +262,6 @@ func SignPKCS1v15(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed [
|
||||
// returning a nil error. If hash is zero then hashed is used directly. This
|
||||
// isn't advisable except for interoperability.
|
||||
func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) error {
|
||||
if boring.Enabled {
|
||||
bkey, err := boringPublicKey(pub)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := boring.VerifyRSAPKCS1v15(bkey, hash, hashed, sig); err != nil {
|
||||
return ErrVerification
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed))
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -64,7 +64,7 @@ func TestDecryptPKCS1v15(t *testing.T) {
|
||||
for i, test := range decryptPKCS1v15Tests {
|
||||
out, err := decryptFunc(decodeBase64(test.in))
|
||||
if err != nil {
|
||||
t.Errorf("#%d error decrypting: %v", i, err)
|
||||
t.Errorf("#%d error decrypting", i)
|
||||
}
|
||||
want := []byte(test.out)
|
||||
if !bytes.Equal(out, want) {
|
||||
|
||||
@@ -11,7 +11,6 @@ package rsa
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/internal/boring"
|
||||
"errors"
|
||||
"hash"
|
||||
"io"
|
||||
@@ -198,22 +197,6 @@ func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed,
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if boring.Enabled {
|
||||
boringFakeRandomBlind(rand, priv)
|
||||
bkey, err := boringPrivateKey(priv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Note: BoringCrypto takes care of the "AndCheck" part of "decryptAndCheck".
|
||||
// (It's not just decrypt.)
|
||||
s, err := boring.DecryptRSANoPadding(bkey, em)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
m := new(big.Int).SetBytes(em)
|
||||
c, err := decryptAndCheck(rand, priv, m)
|
||||
if err != nil {
|
||||
@@ -276,14 +259,6 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte,
|
||||
hash = opts.Hash
|
||||
}
|
||||
|
||||
if boring.Enabled && rand == boring.RandReader {
|
||||
bkey, err := boringPrivateKey(priv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return boring.SignRSAPSS(bkey, hash, hashed, saltLength)
|
||||
}
|
||||
|
||||
salt := make([]byte, saltLength)
|
||||
if _, err := io.ReadFull(rand, salt); err != nil {
|
||||
return nil, err
|
||||
@@ -302,16 +277,6 @@ func VerifyPSS(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte, opts
|
||||
|
||||
// verifyPSS verifies a PSS signature with the given salt length.
|
||||
func verifyPSS(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte, saltLen int) error {
|
||||
if boring.Enabled {
|
||||
bkey, err := boringPublicKey(pub)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := boring.VerifyRSAPSS(bkey, hash, hashed, sig, saltLen); err != nil {
|
||||
return ErrVerification
|
||||
}
|
||||
return nil
|
||||
}
|
||||
nBits := pub.N.BitLen()
|
||||
if len(sig) != (nBits+7)/8 {
|
||||
return ErrVerification
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"bytes"
|
||||
"compress/bzip2"
|
||||
"crypto"
|
||||
_ "crypto/md5"
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
_ "crypto/sha256"
|
||||
@@ -210,7 +211,7 @@ func TestPSSSigning(t *testing.T) {
|
||||
{8, 8, true},
|
||||
}
|
||||
|
||||
hash := crypto.SHA1
|
||||
hash := crypto.MD5
|
||||
h := hash.New()
|
||||
h.Write([]byte("testing"))
|
||||
hashed := h.Sum(nil)
|
||||
|
||||
@@ -24,7 +24,6 @@ package rsa
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/internal/boring"
|
||||
"crypto/rand"
|
||||
"crypto/subtle"
|
||||
"errors"
|
||||
@@ -32,7 +31,6 @@ import (
|
||||
"io"
|
||||
"math"
|
||||
"math/big"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var bigZero = big.NewInt(0)
|
||||
@@ -42,8 +40,6 @@ var bigOne = big.NewInt(1)
|
||||
type PublicKey struct {
|
||||
N *big.Int // modulus
|
||||
E int // public exponent
|
||||
|
||||
boring unsafe.Pointer
|
||||
}
|
||||
|
||||
// OAEPOptions is an interface for passing options to OAEP decryption using the
|
||||
@@ -89,8 +85,6 @@ type PrivateKey struct {
|
||||
// Precomputed contains precomputed values that speed up private
|
||||
// operations, if available.
|
||||
Precomputed PrecomputedValues
|
||||
|
||||
boring unsafe.Pointer
|
||||
}
|
||||
|
||||
// Public returns the public key corresponding to priv.
|
||||
@@ -216,32 +210,6 @@ func GenerateKey(random io.Reader, bits int) (*PrivateKey, error) {
|
||||
// [1] US patent 4405829 (1972, expired)
|
||||
// [2] http://www.cacr.math.uwaterloo.ca/techreports/2006/cacr2006-16.pdf
|
||||
func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (*PrivateKey, error) {
|
||||
if boring.Enabled && random == boring.RandReader && nprimes == 2 && (bits == 2048 || bits == 3072) {
|
||||
N, E, D, P, Q, Dp, Dq, Qinv, err := boring.GenerateKeyRSA(bits)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
e64 := E.Int64()
|
||||
if E.Cmp(big.NewInt(e64)) != 0 || int64(int(e64)) != e64 {
|
||||
return nil, errors.New("crypto/rsa: generated key exponent too large")
|
||||
}
|
||||
key := &PrivateKey{
|
||||
PublicKey: PublicKey{
|
||||
N: N,
|
||||
E: int(e64),
|
||||
},
|
||||
D: D,
|
||||
Primes: []*big.Int{P, Q},
|
||||
Precomputed: PrecomputedValues{
|
||||
Dp: Dp,
|
||||
Dq: Dq,
|
||||
Qinv: Qinv,
|
||||
CRTValues: make([]CRTValue, 0), // non-nil, to match Precompute
|
||||
},
|
||||
}
|
||||
return key, nil
|
||||
}
|
||||
|
||||
priv := new(PrivateKey)
|
||||
priv.E = 65537
|
||||
|
||||
@@ -376,7 +344,6 @@ func mgf1XOR(out []byte, hash hash.Hash, seed []byte) {
|
||||
var ErrMessageTooLong = errors.New("crypto/rsa: message too long for RSA public key size")
|
||||
|
||||
func encrypt(c *big.Int, pub *PublicKey, m *big.Int) *big.Int {
|
||||
boring.Unreachable()
|
||||
e := big.NewInt(int64(pub.E))
|
||||
c.Exp(m, e, pub.N)
|
||||
return c
|
||||
@@ -409,15 +376,6 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l
|
||||
return nil, ErrMessageTooLong
|
||||
}
|
||||
|
||||
if boring.Enabled && random == boring.RandReader {
|
||||
bkey, err := boringPublicKey(pub)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return boring.EncryptRSAOAEP(hash, bkey, msg, label)
|
||||
}
|
||||
boring.UnreachableExceptTests()
|
||||
|
||||
hash.Write(label)
|
||||
lHash := hash.Sum(nil)
|
||||
hash.Reset()
|
||||
@@ -438,24 +396,10 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l
|
||||
mgf1XOR(db, hash, seed)
|
||||
mgf1XOR(seed, hash, db)
|
||||
|
||||
var out []byte
|
||||
if boring.Enabled {
|
||||
var bkey *boring.PublicKeyRSA
|
||||
bkey, err = boringPublicKey(pub)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c, err := boring.EncryptRSANoPadding(bkey, em)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = c
|
||||
} else {
|
||||
m := new(big.Int)
|
||||
m.SetBytes(em)
|
||||
c := encrypt(new(big.Int), pub, m)
|
||||
out = c.Bytes()
|
||||
}
|
||||
m := new(big.Int)
|
||||
m.SetBytes(em)
|
||||
c := encrypt(new(big.Int), pub, m)
|
||||
out := c.Bytes()
|
||||
|
||||
if len(out) < k {
|
||||
// If the output is too small, we need to left-pad with zeros.
|
||||
@@ -533,9 +477,6 @@ func (priv *PrivateKey) Precompute() {
|
||||
// decrypt performs an RSA decryption, resulting in a plaintext integer. If a
|
||||
// random source is given, RSA blinding is used.
|
||||
func decrypt(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err error) {
|
||||
if len(priv.Primes) <= 2 {
|
||||
boring.Unreachable()
|
||||
}
|
||||
// TODO(agl): can we get away with reusing blinds?
|
||||
if c.Cmp(priv.N) > 0 {
|
||||
err = ErrDecryption
|
||||
@@ -651,18 +592,6 @@ func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext
|
||||
return nil, ErrDecryption
|
||||
}
|
||||
|
||||
if boring.Enabled {
|
||||
boringFakeRandomBlind(random, priv)
|
||||
bkey, err := boringPrivateKey(priv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := boring.DecryptRSAOAEP(hash, bkey, ciphertext, label)
|
||||
if err != nil {
|
||||
return nil, ErrDecryption
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
c := new(big.Int).SetBytes(ciphertext)
|
||||
|
||||
m, err := decrypt(random, priv, c)
|
||||
|
||||
@@ -7,29 +7,26 @@ package rsa
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/internal/boring"
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestKeyGeneration(t *testing.T) {
|
||||
for _, size := range []int{128, 1024, 2048, 3072} {
|
||||
priv, err := GenerateKey(rand.Reader, size)
|
||||
if err != nil {
|
||||
t.Errorf("GenerateKey(%d): %v", size, err)
|
||||
}
|
||||
if bits := priv.N.BitLen(); bits != size {
|
||||
t.Errorf("key too short (%d vs %d)", bits, size)
|
||||
}
|
||||
testKeyBasics(t, priv)
|
||||
if testing.Short() {
|
||||
break
|
||||
}
|
||||
size := 1024
|
||||
if testing.Short() {
|
||||
size = 128
|
||||
}
|
||||
priv, err := GenerateKey(rand.Reader, size)
|
||||
if err != nil {
|
||||
t.Errorf("failed to generate key")
|
||||
}
|
||||
if bits := priv.N.BitLen(); bits != size {
|
||||
t.Errorf("key too short (%d vs %d)", bits, size)
|
||||
}
|
||||
testKeyBasics(t, priv)
|
||||
}
|
||||
|
||||
func Test3PrimeKeyGeneration(t *testing.T) {
|
||||
@@ -113,25 +110,6 @@ func testKeyBasics(t *testing.T, priv *PrivateKey) {
|
||||
t.Errorf("private exponent too large")
|
||||
}
|
||||
|
||||
if boring.Enabled {
|
||||
// Cannot call encrypt/decrypt directly. Test via PKCS1v15.
|
||||
msg := []byte("hi!")
|
||||
enc, err := EncryptPKCS1v15(rand.Reader, &priv.PublicKey, msg)
|
||||
if err != nil {
|
||||
t.Errorf("EncryptPKCS1v15: %v", err)
|
||||
return
|
||||
}
|
||||
dec, err := DecryptPKCS1v15(rand.Reader, priv, enc)
|
||||
if err != nil {
|
||||
t.Errorf("DecryptPKCS1v15: %v", err)
|
||||
return
|
||||
}
|
||||
if !bytes.Equal(dec, msg) {
|
||||
t.Errorf("got:%x want:%x (%+v)", dec, msg, priv)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
pub := &priv.PublicKey
|
||||
m := big.NewInt(42)
|
||||
c := encrypt(new(big.Int), pub, m)
|
||||
@@ -180,10 +158,6 @@ func init() {
|
||||
}
|
||||
|
||||
func BenchmarkRSA2048Decrypt(b *testing.B) {
|
||||
if boring.Enabled {
|
||||
b.Skip("no raw decrypt in BoringCrypto")
|
||||
}
|
||||
|
||||
b.StopTimer()
|
||||
|
||||
c := fromBase10("8472002792838218989464636159316973636630013835787202418124758118372358261975764365740026024610403138425986214991379012696600761514742817632790916315594342398720903716529235119816755589383377471752116975374952783629225022962092351886861518911824745188989071172097120352727368980275252089141512321893536744324822590480751098257559766328893767334861211872318961900897793874075248286439689249972315699410830094164386544311554704755110361048571142336148077772023880664786019636334369759624917224888206329520528064315309519262325023881707530002540634660750469137117568199824615333883758410040459705787022909848740188613313")
|
||||
@@ -206,10 +180,6 @@ func BenchmarkRSA2048Sign(b *testing.B) {
|
||||
}
|
||||
|
||||
func Benchmark3PrimeRSA2048Decrypt(b *testing.B) {
|
||||
if boring.Enabled {
|
||||
b.Skip("no raw decrypt in BoringCrypto")
|
||||
}
|
||||
|
||||
b.StopTimer()
|
||||
priv := &PrivateKey{
|
||||
PublicKey: PublicKey{
|
||||
@@ -252,7 +222,7 @@ func TestEncryptOAEP(t *testing.T) {
|
||||
n := new(big.Int)
|
||||
for i, test := range testEncryptOAEPData {
|
||||
n.SetString(test.modulus, 16)
|
||||
public := PublicKey{N: n, E: test.e}
|
||||
public := PublicKey{n, test.e}
|
||||
|
||||
for j, message := range test.msgs {
|
||||
randomSource := bytes.NewReader(message.seed)
|
||||
@@ -277,7 +247,7 @@ func TestDecryptOAEP(t *testing.T) {
|
||||
n.SetString(test.modulus, 16)
|
||||
d.SetString(test.d, 16)
|
||||
private := new(PrivateKey)
|
||||
private.PublicKey = PublicKey{N: n, E: test.e}
|
||||
private.PublicKey = PublicKey{n, test.e}
|
||||
private.D = d
|
||||
|
||||
for j, message := range test.msgs {
|
||||
@@ -302,36 +272,6 @@ func TestDecryptOAEP(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncryptDecryptOAEP(t *testing.T) {
|
||||
sha256 := sha256.New()
|
||||
n := new(big.Int)
|
||||
d := new(big.Int)
|
||||
for i, test := range testEncryptOAEPData {
|
||||
n.SetString(test.modulus, 16)
|
||||
d.SetString(test.d, 16)
|
||||
priv := new(PrivateKey)
|
||||
priv.PublicKey = PublicKey{N: n, E: test.e}
|
||||
priv.D = d
|
||||
|
||||
for j, message := range test.msgs {
|
||||
label := []byte(fmt.Sprintf("hi#%d", j))
|
||||
enc, err := EncryptOAEP(sha256, rand.Reader, &priv.PublicKey, message.in, label)
|
||||
if err != nil {
|
||||
t.Errorf("#%d,%d: EncryptOAEP: %v", i, j, err)
|
||||
continue
|
||||
}
|
||||
dec, err := DecryptOAEP(sha256, rand.Reader, priv, enc, label)
|
||||
if err != nil {
|
||||
t.Errorf("#%d,%d: DecryptOAEP: %v", i, j, err)
|
||||
continue
|
||||
}
|
||||
if !bytes.Equal(dec, message.in) {
|
||||
t.Errorf("#%d,%d: round trip %q -> %q", i, j, message.in, dec)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// testEncryptOAEPData contains a subset of the vectors from RSA's "Test vectors for RSA-OAEP".
|
||||
var testEncryptOAEPData = []testEncryptOAEPStruct{
|
||||
// Key 1
|
||||
|
||||
@@ -1,22 +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.
|
||||
|
||||
// Extra indirection here so that when building go_bootstrap
|
||||
// cmd/internal/boring is not even imported, so that we don't
|
||||
// have to maintain changes to cmd/dist's deps graph.
|
||||
|
||||
// +build !cmd_go_bootstrap
|
||||
|
||||
package sha1
|
||||
|
||||
import (
|
||||
"crypto/internal/boring"
|
||||
"hash"
|
||||
)
|
||||
|
||||
const boringEnabled = boring.Enabled
|
||||
|
||||
func boringNewSHA1() hash.Hash { return boring.NewSHA1() }
|
||||
|
||||
func boringUnreachable() { boring.Unreachable() }
|
||||
@@ -1,17 +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.
|
||||
|
||||
// +build cmd_go_bootstrap
|
||||
|
||||
package sha1
|
||||
|
||||
import (
|
||||
"hash"
|
||||
)
|
||||
|
||||
const boringEnabled = false
|
||||
|
||||
func boringNewSHA1() hash.Hash { panic("boringcrypto: not available") }
|
||||
|
||||
func boringUnreachable() {}
|
||||
@@ -49,9 +49,6 @@ func (d *digest) Reset() {
|
||||
|
||||
// New returns a new hash.Hash computing the SHA1 checksum.
|
||||
func New() hash.Hash {
|
||||
if boringEnabled {
|
||||
return boringNewSHA1()
|
||||
}
|
||||
d := new(digest)
|
||||
d.Reset()
|
||||
return d
|
||||
@@ -62,7 +59,6 @@ func (d *digest) Size() int { return Size }
|
||||
func (d *digest) BlockSize() int { return BlockSize }
|
||||
|
||||
func (d *digest) Write(p []byte) (nn int, err error) {
|
||||
boringUnreachable()
|
||||
nn = len(p)
|
||||
d.len += uint64(nn)
|
||||
if d.nx > 0 {
|
||||
@@ -86,7 +82,6 @@ func (d *digest) Write(p []byte) (nn int, err error) {
|
||||
}
|
||||
|
||||
func (d0 *digest) Sum(in []byte) []byte {
|
||||
boringUnreachable()
|
||||
// Make a copy of d0 so that caller can keep writing and summing.
|
||||
d := *d0
|
||||
hash := d.checkSum()
|
||||
@@ -196,13 +191,6 @@ func (d *digest) constSum() [Size]byte {
|
||||
|
||||
// Sum returns the SHA1 checksum of the data.
|
||||
func Sum(data []byte) [Size]byte {
|
||||
if boringEnabled {
|
||||
h := New()
|
||||
h.Write(data)
|
||||
var ret [Size]byte
|
||||
h.Sum(ret[:0])
|
||||
return ret
|
||||
}
|
||||
var d digest
|
||||
d.Reset()
|
||||
d.Write(data)
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
package sha1
|
||||
|
||||
import (
|
||||
"crypto/internal/boring"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -74,9 +73,6 @@ func TestGolden(t *testing.T) {
|
||||
io.WriteString(c, g.in[len(g.in)/2:])
|
||||
sum = c.Sum(nil)
|
||||
case 3:
|
||||
if boring.Enabled {
|
||||
continue
|
||||
}
|
||||
io.WriteString(c, g.in[0:len(g.in)/2])
|
||||
c.(*digest).ConstantTimeSum(nil)
|
||||
io.WriteString(c, g.in[len(g.in)/2:])
|
||||
@@ -107,9 +103,6 @@ func TestBlockSize(t *testing.T) {
|
||||
|
||||
// Tests that blockGeneric (pure Go) and block (in assembly for some architectures) match.
|
||||
func TestBlockGeneric(t *testing.T) {
|
||||
if boring.Enabled {
|
||||
t.Skip("BoringCrypto doesn't expose digest")
|
||||
}
|
||||
for i := 1; i < 30; i++ { // arbitrary factor
|
||||
gen, asm := New().(*digest), New().(*digest)
|
||||
buf := make([]byte, BlockSize*i)
|
||||
|
||||
@@ -8,7 +8,6 @@ package sha256
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/internal/boring"
|
||||
"hash"
|
||||
)
|
||||
|
||||
@@ -81,9 +80,6 @@ func (d *digest) Reset() {
|
||||
|
||||
// New returns a new hash.Hash computing the SHA256 checksum.
|
||||
func New() hash.Hash {
|
||||
if boring.Enabled {
|
||||
return boring.NewSHA256()
|
||||
}
|
||||
d := new(digest)
|
||||
d.Reset()
|
||||
return d
|
||||
@@ -91,9 +87,6 @@ func New() hash.Hash {
|
||||
|
||||
// New224 returns a new hash.Hash computing the SHA224 checksum.
|
||||
func New224() hash.Hash {
|
||||
if boring.Enabled {
|
||||
return boring.NewSHA224()
|
||||
}
|
||||
d := new(digest)
|
||||
d.is224 = true
|
||||
d.Reset()
|
||||
@@ -110,7 +103,6 @@ func (d *digest) Size() int {
|
||||
func (d *digest) BlockSize() int { return BlockSize }
|
||||
|
||||
func (d *digest) Write(p []byte) (nn int, err error) {
|
||||
boring.Unreachable()
|
||||
nn = len(p)
|
||||
d.len += uint64(nn)
|
||||
if d.nx > 0 {
|
||||
@@ -134,7 +126,6 @@ func (d *digest) Write(p []byte) (nn int, err error) {
|
||||
}
|
||||
|
||||
func (d0 *digest) Sum(in []byte) []byte {
|
||||
boring.Unreachable()
|
||||
// Make a copy of d0 so that caller can keep writing and summing.
|
||||
d := *d0
|
||||
hash := d.checkSum()
|
||||
@@ -184,13 +175,6 @@ func (d *digest) checkSum() [Size]byte {
|
||||
|
||||
// Sum256 returns the SHA256 checksum of the data.
|
||||
func Sum256(data []byte) [Size]byte {
|
||||
if boring.Enabled {
|
||||
h := New()
|
||||
h.Write(data)
|
||||
var ret [Size]byte
|
||||
h.Sum(ret[:0])
|
||||
return ret
|
||||
}
|
||||
var d digest
|
||||
d.Reset()
|
||||
d.Write(data)
|
||||
@@ -199,13 +183,6 @@ func Sum256(data []byte) [Size]byte {
|
||||
|
||||
// Sum224 returns the SHA224 checksum of the data.
|
||||
func Sum224(data []byte) (sum224 [Size224]byte) {
|
||||
if boring.Enabled {
|
||||
h := New224()
|
||||
h.Write(data)
|
||||
var ret [Size224]byte
|
||||
h.Sum(ret[:0])
|
||||
return ret
|
||||
}
|
||||
var d digest
|
||||
d.is224 = true
|
||||
d.Reset()
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
package sha256
|
||||
|
||||
import (
|
||||
"crypto/internal/boring"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -154,9 +153,6 @@ func TestBlockSize(t *testing.T) {
|
||||
|
||||
// Tests that blockGeneric (pure Go) and block (in assembly for some architectures) match.
|
||||
func TestBlockGeneric(t *testing.T) {
|
||||
if boring.Enabled {
|
||||
t.Skip("BoringCrypto doesn't expose digest")
|
||||
}
|
||||
gen, asm := New().(*digest), New().(*digest)
|
||||
buf := make([]byte, BlockSize*20) // arbitrary factor
|
||||
rand.Read(buf)
|
||||
|
||||
@@ -8,7 +8,6 @@ package sha512
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/internal/boring"
|
||||
"hash"
|
||||
)
|
||||
|
||||
@@ -127,9 +126,6 @@ func (d *digest) Reset() {
|
||||
|
||||
// New returns a new hash.Hash computing the SHA-512 checksum.
|
||||
func New() hash.Hash {
|
||||
if boring.Enabled {
|
||||
return boring.NewSHA512()
|
||||
}
|
||||
d := &digest{function: crypto.SHA512}
|
||||
d.Reset()
|
||||
return d
|
||||
@@ -151,9 +147,6 @@ func New512_256() hash.Hash {
|
||||
|
||||
// New384 returns a new hash.Hash computing the SHA-384 checksum.
|
||||
func New384() hash.Hash {
|
||||
if boring.Enabled {
|
||||
return boring.NewSHA384()
|
||||
}
|
||||
d := &digest{function: crypto.SHA384}
|
||||
d.Reset()
|
||||
return d
|
||||
@@ -175,9 +168,6 @@ func (d *digest) Size() int {
|
||||
func (d *digest) BlockSize() int { return BlockSize }
|
||||
|
||||
func (d *digest) Write(p []byte) (nn int, err error) {
|
||||
if d.function != crypto.SHA512_224 && d.function != crypto.SHA512_256 {
|
||||
boring.Unreachable()
|
||||
}
|
||||
nn = len(p)
|
||||
d.len += uint64(nn)
|
||||
if d.nx > 0 {
|
||||
@@ -201,9 +191,6 @@ func (d *digest) Write(p []byte) (nn int, err error) {
|
||||
}
|
||||
|
||||
func (d0 *digest) Sum(in []byte) []byte {
|
||||
if d0.function != crypto.SHA512_224 && d0.function != crypto.SHA512_256 {
|
||||
boring.Unreachable()
|
||||
}
|
||||
// Make a copy of d0 so that caller can keep writing and summing.
|
||||
d := new(digest)
|
||||
*d = *d0
|
||||
@@ -264,13 +251,6 @@ func (d *digest) checkSum() [Size]byte {
|
||||
|
||||
// Sum512 returns the SHA512 checksum of the data.
|
||||
func Sum512(data []byte) [Size]byte {
|
||||
if boring.Enabled {
|
||||
h := New()
|
||||
h.Write(data)
|
||||
var ret [Size]byte
|
||||
h.Sum(ret[:0])
|
||||
return ret
|
||||
}
|
||||
d := digest{function: crypto.SHA512}
|
||||
d.Reset()
|
||||
d.Write(data)
|
||||
@@ -279,13 +259,6 @@ func Sum512(data []byte) [Size]byte {
|
||||
|
||||
// Sum384 returns the SHA384 checksum of the data.
|
||||
func Sum384(data []byte) (sum384 [Size384]byte) {
|
||||
if boring.Enabled {
|
||||
h := New384()
|
||||
h.Write(data)
|
||||
var ret [Size384]byte
|
||||
h.Sum(ret[:0])
|
||||
return ret
|
||||
}
|
||||
d := digest{function: crypto.SHA384}
|
||||
d.Reset()
|
||||
d.Write(data)
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
package sha512
|
||||
|
||||
import (
|
||||
"crypto/internal/boring"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"hash"
|
||||
@@ -308,9 +307,6 @@ func TestBlockSize(t *testing.T) {
|
||||
|
||||
// Tests that blockGeneric (pure Go) and block (in assembly for some architectures) match.
|
||||
func TestBlockGeneric(t *testing.T) {
|
||||
if boring.Enabled {
|
||||
t.Skip("BoringCrypto doesn't expose digest")
|
||||
}
|
||||
gen, asm := New().(*digest), New().(*digest)
|
||||
buf := make([]byte, BlockSize*20) // arbitrary factor
|
||||
rand.Read(buf)
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
// Copyright 2017 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/ecdsa"
|
||||
"crypto/internal/boring/fipstls"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
)
|
||||
|
||||
// needFIPS returns fipstls.Required(); it avoids a new import in common.go.
|
||||
func needFIPS() bool {
|
||||
return fipstls.Required()
|
||||
}
|
||||
|
||||
// fipsMinVersion replaces c.minVersion in FIPS-only mode.
|
||||
func fipsMinVersion(c *Config) uint16 {
|
||||
// FIPS requires TLS 1.2.
|
||||
return VersionTLS12
|
||||
}
|
||||
|
||||
// fipsMaxVersion replaces c.maxVersion in FIPS-only mode.
|
||||
func fipsMaxVersion(c *Config) uint16 {
|
||||
// FIPS requires TLS 1.2.
|
||||
return VersionTLS12
|
||||
}
|
||||
|
||||
// default defaultFIPSCurvePreferences is the FIPS-allowed curves,
|
||||
// in preference order (most preferable first).
|
||||
var defaultFIPSCurvePreferences = []CurveID{CurveP256, CurveP384, CurveP521}
|
||||
|
||||
// fipsCurvePreferences replaces c.curvePreferences in FIPS-only mode.
|
||||
func fipsCurvePreferences(c *Config) []CurveID {
|
||||
if c == nil || len(c.CurvePreferences) == 0 {
|
||||
return defaultFIPSCurvePreferences
|
||||
}
|
||||
var list []CurveID
|
||||
for _, id := range c.CurvePreferences {
|
||||
for _, allowed := range defaultFIPSCurvePreferences {
|
||||
if id == allowed {
|
||||
list = append(list, id)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
// default FIPSCipherSuites is the FIPS-allowed cipher suites,
|
||||
// in preference order (most preferable first).
|
||||
var defaultFIPSCipherSuites = []uint16{
|
||||
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
TLS_RSA_WITH_AES_128_GCM_SHA256,
|
||||
TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||
}
|
||||
|
||||
// fipsCipherSuites replaces c.cipherSuites in FIPS-only mode.
|
||||
func fipsCipherSuites(c *Config) []uint16 {
|
||||
if c == nil || c.CipherSuites == nil {
|
||||
return defaultFIPSCipherSuites
|
||||
}
|
||||
var list []uint16
|
||||
for _, id := range c.CipherSuites {
|
||||
for _, allowed := range defaultFIPSCipherSuites {
|
||||
if id == allowed {
|
||||
list = append(list, id)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
// isBoringCertificate reports whether a certificate may be used
|
||||
// when constructing a verified chain.
|
||||
// It is called for each leaf, intermediate, and root certificate.
|
||||
func isBoringCertificate(c *x509.Certificate) bool {
|
||||
if !needFIPS() {
|
||||
// Everything is OK if we haven't forced FIPS-only mode.
|
||||
return true
|
||||
}
|
||||
|
||||
// Otherwise the key must be RSA 2048, RSA 3072, or ECDSA P-256.
|
||||
switch k := c.PublicKey.(type) {
|
||||
default:
|
||||
return false
|
||||
case *rsa.PublicKey:
|
||||
if size := k.N.BitLen(); size != 2048 && size != 3072 {
|
||||
return false
|
||||
}
|
||||
case *ecdsa.PublicKey:
|
||||
if name := k.Curve.Params().Name; name != "P-256" && name != "P-384" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// supportedSignatureAlgorithms returns the supported signature algorithms.
|
||||
// It knows that the FIPS-allowed ones are all at the beginning of
|
||||
// defaultSupportedSignatureAlgorithms.
|
||||
func supportedSignatureAlgorithms() []signatureAndHash {
|
||||
all := defaultSupportedSignatureAlgorithms
|
||||
if !needFIPS() {
|
||||
return all
|
||||
}
|
||||
i := 0
|
||||
for i < len(all) && all[i].hash != hashSHA1 {
|
||||
i++
|
||||
}
|
||||
return all[:i]
|
||||
}
|
||||
|
||||
var testingOnlyForceClientHelloSignatureAndHashes []signatureAndHash
|
||||
@@ -1,579 +0,0 @@
|
||||
// Copyright 2017 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/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/internal/boring/fipstls"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"net"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestBoringServerProtocolVersion(t *testing.T) {
|
||||
test := func(name string, v uint16, msg string) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
serverConfig := testConfig.Clone()
|
||||
serverConfig.MinVersion = VersionSSL30
|
||||
clientHello := &clientHelloMsg{
|
||||
vers: v,
|
||||
cipherSuites: allCipherSuites(),
|
||||
compressionMethods: []uint8{compressionNone},
|
||||
}
|
||||
testClientHelloFailure(t, serverConfig, clientHello, msg)
|
||||
})
|
||||
}
|
||||
|
||||
test("VersionSSL30", VersionSSL30, "")
|
||||
test("VersionTLS10", VersionTLS10, "")
|
||||
test("VersionTLS11", VersionTLS11, "")
|
||||
test("VersionTLS12", VersionTLS12, "")
|
||||
|
||||
fipstls.Force()
|
||||
defer fipstls.Abandon()
|
||||
test("VersionSSL30", VersionSSL30, "unsupported, maximum protocol version")
|
||||
test("VersionTLS10", VersionTLS10, "unsupported, maximum protocol version")
|
||||
test("VersionTLS11", VersionTLS11, "unsupported, maximum protocol version")
|
||||
test("VersionTLS12", VersionTLS12, "")
|
||||
}
|
||||
|
||||
func isBoringCipherSuite(id uint16) bool {
|
||||
switch id {
|
||||
case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
TLS_RSA_WITH_AES_128_GCM_SHA256,
|
||||
TLS_RSA_WITH_AES_256_GCM_SHA384:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isBoringCurve(id CurveID) bool {
|
||||
switch id {
|
||||
case CurveP256, CurveP384, CurveP521:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isECDSA(id uint16) bool {
|
||||
for _, suite := range cipherSuites {
|
||||
if suite.id == id {
|
||||
return suite.flags&suiteECDSA == suiteECDSA
|
||||
}
|
||||
}
|
||||
panic(fmt.Sprintf("unknown cipher suite %#x", id))
|
||||
}
|
||||
|
||||
func isBoringSignatureAndHash(sigHash signatureAndHash) bool {
|
||||
switch sigHash.signature {
|
||||
default:
|
||||
return false
|
||||
case signatureRSA,
|
||||
signatureECDSA:
|
||||
// ok
|
||||
}
|
||||
switch sigHash.hash {
|
||||
default:
|
||||
return false
|
||||
case hashSHA256,
|
||||
hashSHA384:
|
||||
// ok
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func TestBoringServerCipherSuites(t *testing.T) {
|
||||
serverConfig := testConfig.Clone()
|
||||
serverConfig.CipherSuites = allCipherSuites()
|
||||
serverConfig.Certificates = make([]Certificate, 1)
|
||||
|
||||
for _, id := range allCipherSuites() {
|
||||
if isECDSA(id) {
|
||||
serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate}
|
||||
serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey
|
||||
} else {
|
||||
serverConfig.Certificates[0].Certificate = [][]byte{testRSACertificate}
|
||||
serverConfig.Certificates[0].PrivateKey = testRSAPrivateKey
|
||||
}
|
||||
serverConfig.BuildNameToCertificate()
|
||||
t.Run(fmt.Sprintf("suite=%#x", id), func(t *testing.T) {
|
||||
clientHello := &clientHelloMsg{
|
||||
vers: VersionTLS12,
|
||||
cipherSuites: []uint16{id},
|
||||
compressionMethods: []uint8{compressionNone},
|
||||
supportedCurves: defaultCurvePreferences,
|
||||
supportedPoints: []uint8{pointFormatUncompressed},
|
||||
}
|
||||
|
||||
testClientHello(t, serverConfig, clientHello)
|
||||
t.Run("fipstls", func(t *testing.T) {
|
||||
fipstls.Force()
|
||||
defer fipstls.Abandon()
|
||||
msg := ""
|
||||
if !isBoringCipherSuite(id) {
|
||||
msg = "no cipher suite supported by both client and server"
|
||||
}
|
||||
testClientHelloFailure(t, serverConfig, clientHello, msg)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBoringServerCurves(t *testing.T) {
|
||||
serverConfig := testConfig.Clone()
|
||||
serverConfig.Certificates = make([]Certificate, 1)
|
||||
serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate}
|
||||
serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey
|
||||
serverConfig.BuildNameToCertificate()
|
||||
|
||||
for _, curveid := range defaultCurvePreferences {
|
||||
t.Run(fmt.Sprintf("curve=%d", curveid), func(t *testing.T) {
|
||||
clientHello := &clientHelloMsg{
|
||||
vers: VersionTLS12,
|
||||
cipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
|
||||
compressionMethods: []uint8{compressionNone},
|
||||
supportedCurves: []CurveID{curveid},
|
||||
supportedPoints: []uint8{pointFormatUncompressed},
|
||||
}
|
||||
|
||||
testClientHello(t, serverConfig, clientHello)
|
||||
|
||||
// With fipstls forced, bad curves should be rejected.
|
||||
t.Run("fipstls", func(t *testing.T) {
|
||||
fipstls.Force()
|
||||
defer fipstls.Abandon()
|
||||
msg := ""
|
||||
if !isBoringCurve(curveid) {
|
||||
msg = "no cipher suite supported by both client and server"
|
||||
}
|
||||
testClientHelloFailure(t, serverConfig, clientHello, msg)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func boringHandshake(t *testing.T, clientConfig, serverConfig *Config) (clientErr, serverErr error) {
|
||||
c, s := realNetPipe(t)
|
||||
client := Client(c, clientConfig)
|
||||
server := Server(s, serverConfig)
|
||||
done := make(chan error, 1)
|
||||
go func() {
|
||||
done <- client.Handshake()
|
||||
c.Close()
|
||||
}()
|
||||
serverErr = server.Handshake()
|
||||
s.Close()
|
||||
clientErr = <-done
|
||||
return
|
||||
}
|
||||
|
||||
func TestBoringServerSignatureAndHash(t *testing.T) {
|
||||
serverConfig := testConfig.Clone()
|
||||
serverConfig.Certificates = make([]Certificate, 1)
|
||||
|
||||
defer func() {
|
||||
testingOnlyForceClientHelloSignatureAndHashes = nil
|
||||
}()
|
||||
|
||||
for _, sigHash := range defaultSupportedSignatureAlgorithms {
|
||||
testingOnlyForceClientHelloSignatureAndHashes = []signatureAndHash{sigHash}
|
||||
|
||||
t.Run(fmt.Sprintf("%v", sigHash), func(t *testing.T) {
|
||||
if sigHash.signature == signatureRSA {
|
||||
serverConfig.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}
|
||||
serverConfig.Certificates[0].Certificate = [][]byte{testRSACertificate}
|
||||
serverConfig.Certificates[0].PrivateKey = testRSAPrivateKey
|
||||
} else {
|
||||
serverConfig.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}
|
||||
serverConfig.Certificates = make([]Certificate, 1)
|
||||
serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate}
|
||||
serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey
|
||||
}
|
||||
serverConfig.BuildNameToCertificate()
|
||||
|
||||
clientErr, _ := boringHandshake(t, testConfig, serverConfig)
|
||||
if clientErr != nil {
|
||||
t.Fatalf("expected handshake with %v to succeed; err=%v", sigHash, clientErr)
|
||||
}
|
||||
|
||||
// With fipstls forced, bad curves should be rejected.
|
||||
t.Run("fipstls", func(t *testing.T) {
|
||||
fipstls.Force()
|
||||
defer fipstls.Abandon()
|
||||
clientErr, _ := boringHandshake(t, testConfig, serverConfig)
|
||||
if isBoringSignatureAndHash(sigHash) {
|
||||
if clientErr != nil {
|
||||
t.Fatalf("expected handshake with %v to succeed; err=%v", sigHash, clientErr)
|
||||
}
|
||||
} else {
|
||||
if clientErr == nil {
|
||||
t.Fatalf("expected handshake with %v to fail, but it succeeded", sigHash)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBoringClientHello(t *testing.T) {
|
||||
// Test that no matter what we put in the client config,
|
||||
// the client does not offer non-FIPS configurations.
|
||||
fipstls.Force()
|
||||
defer fipstls.Abandon()
|
||||
|
||||
c, s := net.Pipe()
|
||||
defer c.Close()
|
||||
defer s.Close()
|
||||
|
||||
clientConfig := testConfig.Clone()
|
||||
// All sorts of traps for the client to avoid.
|
||||
clientConfig.MinVersion = VersionSSL30
|
||||
clientConfig.CipherSuites = allCipherSuites()
|
||||
clientConfig.CurvePreferences = defaultCurvePreferences
|
||||
|
||||
go Client(c, testConfig).Handshake()
|
||||
srv := Server(s, testConfig)
|
||||
msg, err := srv.readHandshake()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
hello, ok := msg.(*clientHelloMsg)
|
||||
if !ok {
|
||||
t.Fatalf("unexpected message type %T", msg)
|
||||
}
|
||||
|
||||
if hello.vers != VersionTLS12 {
|
||||
t.Errorf("client vers=%#x, want %#x (TLS 1.2)", hello.vers, VersionTLS12)
|
||||
}
|
||||
for _, id := range hello.cipherSuites {
|
||||
if !isBoringCipherSuite(id) {
|
||||
t.Errorf("client offered disallowed suite %#x", id)
|
||||
}
|
||||
}
|
||||
for _, id := range hello.supportedCurves {
|
||||
if !isBoringCurve(id) {
|
||||
t.Errorf("client offered disallowed curve %d", id)
|
||||
}
|
||||
}
|
||||
for _, sigHash := range hello.signatureAndHashes {
|
||||
if !isBoringSignatureAndHash(sigHash) {
|
||||
t.Errorf("client offered disallowed signature-and-hash %v", sigHash)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBoringCertAlgs(t *testing.T) {
|
||||
// NaCl and arm time out generating keys. Nothing in this test is architecture-specific, so just don't bother on those.
|
||||
if runtime.GOOS == "nacl" || runtime.GOARCH == "arm" {
|
||||
t.Skipf("skipping on %s/%s because key generation takes too long", runtime.GOOS, runtime.GOARCH)
|
||||
}
|
||||
|
||||
// Set up some roots, intermediate CAs, and leaf certs with various algorithms.
|
||||
// X_Y is X signed by Y.
|
||||
R1 := boringCert(t, "R1", boringRSAKey(t, 2048), nil, boringCertCA|boringCertFIPSOK)
|
||||
R2 := boringCert(t, "R2", boringRSAKey(t, 4096), nil, boringCertCA)
|
||||
|
||||
M1_R1 := boringCert(t, "M1_R1", boringECDSAKey(t, elliptic.P256()), R1, boringCertCA|boringCertFIPSOK)
|
||||
M2_R1 := boringCert(t, "M2_R1", boringECDSAKey(t, elliptic.P224()), R1, boringCertCA)
|
||||
|
||||
I_R1 := boringCert(t, "I_R1", boringRSAKey(t, 3072), R1, boringCertCA|boringCertFIPSOK)
|
||||
I_R2 := boringCert(t, "I_R2", I_R1.key, R2, boringCertCA|boringCertFIPSOK)
|
||||
I_M1 := boringCert(t, "I_M1", I_R1.key, M1_R1, boringCertCA|boringCertFIPSOK)
|
||||
I_M2 := boringCert(t, "I_M2", I_R1.key, M2_R1, boringCertCA|boringCertFIPSOK)
|
||||
|
||||
L1_I := boringCert(t, "L1_I", boringECDSAKey(t, elliptic.P384()), I_R1, boringCertLeaf|boringCertFIPSOK)
|
||||
L2_I := boringCert(t, "L2_I", boringRSAKey(t, 1024), I_R1, boringCertLeaf)
|
||||
|
||||
// boringCert checked that isBoringCertificate matches the caller's boringCertFIPSOK bit.
|
||||
// If not, no point in building bigger end-to-end tests.
|
||||
if t.Failed() {
|
||||
t.Fatalf("isBoringCertificate failures; not continuing")
|
||||
}
|
||||
|
||||
// client verifying server cert
|
||||
testServerCert := func(t *testing.T, desc string, pool *x509.CertPool, key interface{}, list [][]byte, ok bool) {
|
||||
clientConfig := testConfig.Clone()
|
||||
clientConfig.RootCAs = pool
|
||||
clientConfig.InsecureSkipVerify = false
|
||||
clientConfig.ServerName = "example.com"
|
||||
|
||||
serverConfig := testConfig.Clone()
|
||||
serverConfig.Certificates = []Certificate{{Certificate: list, PrivateKey: key}}
|
||||
serverConfig.BuildNameToCertificate()
|
||||
|
||||
clientErr, _ := boringHandshake(t, clientConfig, serverConfig)
|
||||
|
||||
if (clientErr == nil) == ok {
|
||||
if ok {
|
||||
t.Logf("%s: accept", desc)
|
||||
} else {
|
||||
t.Logf("%s: reject", desc)
|
||||
}
|
||||
} else {
|
||||
if ok {
|
||||
t.Errorf("%s: BAD reject (%v)", desc, clientErr)
|
||||
} else {
|
||||
t.Errorf("%s: BAD accept", desc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// server verifying client cert
|
||||
testClientCert := func(t *testing.T, desc string, pool *x509.CertPool, key interface{}, list [][]byte, ok bool) {
|
||||
clientConfig := testConfig.Clone()
|
||||
clientConfig.ServerName = "example.com"
|
||||
clientConfig.Certificates = []Certificate{{Certificate: list, PrivateKey: key}}
|
||||
|
||||
serverConfig := testConfig.Clone()
|
||||
serverConfig.ClientCAs = pool
|
||||
serverConfig.ClientAuth = RequireAndVerifyClientCert
|
||||
|
||||
_, serverErr := boringHandshake(t, clientConfig, serverConfig)
|
||||
|
||||
if (serverErr == nil) == ok {
|
||||
if ok {
|
||||
t.Logf("%s: accept", desc)
|
||||
} else {
|
||||
t.Logf("%s: reject", desc)
|
||||
}
|
||||
} else {
|
||||
if ok {
|
||||
t.Errorf("%s: BAD reject (%v)", desc, serverErr)
|
||||
} else {
|
||||
t.Errorf("%s: BAD accept", desc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Run simple basic test with known answers before proceeding to
|
||||
// exhaustive test with computed answers.
|
||||
r1pool := x509.NewCertPool()
|
||||
r1pool.AddCert(R1.cert)
|
||||
testServerCert(t, "basic", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, true)
|
||||
testClientCert(t, "basic (client cert)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, true)
|
||||
fipstls.Force()
|
||||
testServerCert(t, "basic (fips)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, false)
|
||||
testClientCert(t, "basic (fips, client cert)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, false)
|
||||
fipstls.Abandon()
|
||||
|
||||
if t.Failed() {
|
||||
t.Fatal("basic test failed, skipping exhaustive test")
|
||||
}
|
||||
|
||||
if testing.Short() {
|
||||
t.Logf("basic test passed; skipping exhaustive test in -short mode")
|
||||
return
|
||||
}
|
||||
|
||||
for l := 1; l <= 2; l++ {
|
||||
leaf := L1_I
|
||||
if l == 2 {
|
||||
leaf = L2_I
|
||||
}
|
||||
for i := 0; i < 64; i++ {
|
||||
reachable := map[string]bool{leaf.parentOrg: true}
|
||||
reachableFIPS := map[string]bool{leaf.parentOrg: leaf.fipsOK}
|
||||
list := [][]byte{leaf.der}
|
||||
listName := leaf.name
|
||||
addList := func(cond int, c *boringCertificate) {
|
||||
if cond != 0 {
|
||||
list = append(list, c.der)
|
||||
listName += "," + c.name
|
||||
if reachable[c.org] {
|
||||
reachable[c.parentOrg] = true
|
||||
}
|
||||
if reachableFIPS[c.org] && c.fipsOK {
|
||||
reachableFIPS[c.parentOrg] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
addList(i&1, I_R1)
|
||||
addList(i&2, I_R2)
|
||||
addList(i&4, I_M1)
|
||||
addList(i&8, I_M2)
|
||||
addList(i&16, M1_R1)
|
||||
addList(i&32, M2_R1)
|
||||
|
||||
for r := 1; r <= 3; r++ {
|
||||
pool := x509.NewCertPool()
|
||||
rootName := ","
|
||||
shouldVerify := false
|
||||
shouldVerifyFIPS := false
|
||||
addRoot := func(cond int, c *boringCertificate) {
|
||||
if cond != 0 {
|
||||
rootName += "," + c.name
|
||||
pool.AddCert(c.cert)
|
||||
if reachable[c.org] {
|
||||
shouldVerify = true
|
||||
}
|
||||
if reachableFIPS[c.org] && c.fipsOK {
|
||||
shouldVerifyFIPS = true
|
||||
}
|
||||
}
|
||||
}
|
||||
addRoot(r&1, R1)
|
||||
addRoot(r&2, R2)
|
||||
rootName = rootName[1:] // strip leading comma
|
||||
testServerCert(t, listName+"->"+rootName[1:], pool, leaf.key, list, shouldVerify)
|
||||
testClientCert(t, listName+"->"+rootName[1:]+"(client cert)", pool, leaf.key, list, shouldVerify)
|
||||
fipstls.Force()
|
||||
testServerCert(t, listName+"->"+rootName[1:]+" (fips)", pool, leaf.key, list, shouldVerifyFIPS)
|
||||
testClientCert(t, listName+"->"+rootName[1:]+" (fips, client cert)", pool, leaf.key, list, shouldVerifyFIPS)
|
||||
fipstls.Abandon()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
boringCertCA = iota
|
||||
boringCertLeaf
|
||||
boringCertFIPSOK = 0x80
|
||||
)
|
||||
|
||||
func boringRSAKey(t *testing.T, size int) *rsa.PrivateKey {
|
||||
k, err := rsa.GenerateKey(rand.Reader, size)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return k
|
||||
}
|
||||
|
||||
func boringECDSAKey(t *testing.T, curve elliptic.Curve) *ecdsa.PrivateKey {
|
||||
k, err := ecdsa.GenerateKey(curve, rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return k
|
||||
}
|
||||
|
||||
type boringCertificate struct {
|
||||
name string
|
||||
org string
|
||||
parentOrg string
|
||||
der []byte
|
||||
cert *x509.Certificate
|
||||
key interface{}
|
||||
fipsOK bool
|
||||
}
|
||||
|
||||
func boringCert(t *testing.T, name string, key interface{}, parent *boringCertificate, mode int) *boringCertificate {
|
||||
org := name
|
||||
parentOrg := ""
|
||||
if i := strings.Index(org, "_"); i >= 0 {
|
||||
org = org[:i]
|
||||
parentOrg = name[i+1:]
|
||||
}
|
||||
tmpl := &x509.Certificate{
|
||||
SerialNumber: big.NewInt(1),
|
||||
Subject: pkix.Name{
|
||||
Organization: []string{org},
|
||||
},
|
||||
NotBefore: time.Unix(0, 0),
|
||||
NotAfter: time.Unix(0, 0),
|
||||
|
||||
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
|
||||
BasicConstraintsValid: true,
|
||||
}
|
||||
if mode&^boringCertFIPSOK == boringCertLeaf {
|
||||
tmpl.DNSNames = []string{"example.com"}
|
||||
} else {
|
||||
tmpl.IsCA = true
|
||||
tmpl.KeyUsage |= x509.KeyUsageCertSign
|
||||
}
|
||||
|
||||
var pcert *x509.Certificate
|
||||
var pkey interface{}
|
||||
if parent != nil {
|
||||
pcert = parent.cert
|
||||
pkey = parent.key
|
||||
} else {
|
||||
pcert = tmpl
|
||||
pkey = key
|
||||
}
|
||||
|
||||
var pub interface{}
|
||||
var desc string
|
||||
switch k := key.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
pub = &k.PublicKey
|
||||
desc = fmt.Sprintf("RSA-%d", k.N.BitLen())
|
||||
case *ecdsa.PrivateKey:
|
||||
pub = &k.PublicKey
|
||||
desc = "ECDSA-" + k.Curve.Params().Name
|
||||
default:
|
||||
t.Fatalf("invalid key %T", key)
|
||||
}
|
||||
|
||||
der, err := x509.CreateCertificate(rand.Reader, tmpl, pcert, pub, pkey)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cert, err := x509.ParseCertificate(der)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Tell isBoringCertificate to enforce FIPS restrictions for this check.
|
||||
fipstls.Force()
|
||||
defer fipstls.Abandon()
|
||||
|
||||
fipsOK := mode&boringCertFIPSOK != 0
|
||||
if isBoringCertificate(cert) != fipsOK {
|
||||
t.Errorf("isBoringCertificate(cert with %s key) = %v, want %v", desc, !fipsOK, fipsOK)
|
||||
}
|
||||
return &boringCertificate{name, org, parentOrg, der, cert, key, fipsOK}
|
||||
}
|
||||
|
||||
func boringPool(t *testing.T, list ...*boringCertificate) *x509.CertPool {
|
||||
pool := x509.NewCertPool()
|
||||
for _, c := range list {
|
||||
cert, err := x509.ParseCertificate(c.der)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
pool.AddCert(cert)
|
||||
}
|
||||
return pool
|
||||
}
|
||||
|
||||
func boringList(t *testing.T, list ...*boringCertificate) [][]byte {
|
||||
var all [][]byte
|
||||
for _, c := range list {
|
||||
all = append(all, c.der)
|
||||
}
|
||||
return all
|
||||
}
|
||||
|
||||
// realNetPipe is like net.Pipe but returns an actual network socket pair,
|
||||
// which has buffering that avoids various deadlocks if both sides
|
||||
// try to speak at the same time.
|
||||
func realNetPipe(t *testing.T) (net.Conn, net.Conn) {
|
||||
l := newLocalListener(t)
|
||||
defer l.Close()
|
||||
c, err := net.Dial("tcp", l.Addr().String())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
s, err := l.Accept()
|
||||
if err != nil {
|
||||
c.Close()
|
||||
t.Fatal(err)
|
||||
}
|
||||
return c, s
|
||||
}
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"crypto/cipher"
|
||||
"crypto/des"
|
||||
"crypto/hmac"
|
||||
"crypto/internal/boring"
|
||||
"crypto/rc4"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
@@ -136,11 +135,7 @@ func macSHA1(version uint16, key []byte) macFunction {
|
||||
copy(mac.key, key)
|
||||
return mac
|
||||
}
|
||||
h := sha1.New
|
||||
if !boring.Enabled {
|
||||
h = newConstantTimeHash(h)
|
||||
}
|
||||
return tls10MAC{hmac.New(h, key)}
|
||||
return tls10MAC{hmac.New(newConstantTimeHash(sha1.New), key)}
|
||||
}
|
||||
|
||||
// macSHA256 returns a SHA-256 based MAC. These are only supported in TLS 1.2
|
||||
@@ -220,22 +215,12 @@ func (f *xorNonceAEAD) Open(out, nonce, plaintext, additionalData []byte) ([]byt
|
||||
return result, err
|
||||
}
|
||||
|
||||
type gcmtls interface {
|
||||
NewGCMTLS() (cipher.AEAD, error)
|
||||
}
|
||||
|
||||
func aeadAESGCM(key, fixedNonce []byte) cipher.AEAD {
|
||||
aes, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var aead cipher.AEAD
|
||||
if aesTLS, ok := aes.(gcmtls); ok {
|
||||
aead, err = aesTLS.NewGCMTLS()
|
||||
} else {
|
||||
boring.Unreachable()
|
||||
aead, err = cipher.NewGCM(aes)
|
||||
}
|
||||
aead, err := cipher.NewGCM(aes)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -313,11 +298,6 @@ func (c *cthWrapper) Write(p []byte) (int, error) { return c.h.Write(p) }
|
||||
func (c *cthWrapper) Sum(b []byte) []byte { return c.h.ConstantTimeSum(b) }
|
||||
|
||||
func newConstantTimeHash(h func() hash.Hash) func() hash.Hash {
|
||||
if boring.Enabled {
|
||||
// The BoringCrypto SHA1 does not have a constant-time
|
||||
// checksum function, so don't try to use it.
|
||||
return h
|
||||
}
|
||||
return func() hash.Hash {
|
||||
return &cthWrapper{h().(constantTimeHash)}
|
||||
}
|
||||
|
||||
@@ -145,10 +145,10 @@ type signatureAndHash struct {
|
||||
hash, signature uint8
|
||||
}
|
||||
|
||||
// defaultSupportedSignatureAlgorithms contains the signature and hash algorithms that
|
||||
// supportedSignatureAlgorithms contains the signature and hash algorithms that
|
||||
// the code advertises as supported in a TLS 1.2 ClientHello and in a TLS 1.2
|
||||
// CertificateRequest.
|
||||
var defaultSupportedSignatureAlgorithms = []signatureAndHash{
|
||||
var supportedSignatureAlgorithms = []signatureAndHash{
|
||||
{hashSHA256, signatureRSA},
|
||||
{hashSHA256, signatureECDSA},
|
||||
{hashSHA384, signatureRSA},
|
||||
@@ -670,9 +670,6 @@ func (c *Config) time() time.Time {
|
||||
}
|
||||
|
||||
func (c *Config) cipherSuites() []uint16 {
|
||||
if needFIPS() {
|
||||
return fipsCipherSuites(c)
|
||||
}
|
||||
s := c.CipherSuites
|
||||
if s == nil {
|
||||
s = defaultCipherSuites()
|
||||
@@ -681,9 +678,6 @@ func (c *Config) cipherSuites() []uint16 {
|
||||
}
|
||||
|
||||
func (c *Config) minVersion() uint16 {
|
||||
if needFIPS() {
|
||||
return fipsMinVersion(c)
|
||||
}
|
||||
if c == nil || c.MinVersion == 0 {
|
||||
return minVersion
|
||||
}
|
||||
@@ -691,9 +685,6 @@ func (c *Config) minVersion() uint16 {
|
||||
}
|
||||
|
||||
func (c *Config) maxVersion() uint16 {
|
||||
if needFIPS() {
|
||||
return fipsMaxVersion(c)
|
||||
}
|
||||
if c == nil || c.MaxVersion == 0 {
|
||||
return maxVersion
|
||||
}
|
||||
@@ -703,9 +694,6 @@ func (c *Config) maxVersion() uint16 {
|
||||
var defaultCurvePreferences = []CurveID{X25519, CurveP256, CurveP384, CurveP521}
|
||||
|
||||
func (c *Config) curvePreferences() []CurveID {
|
||||
if needFIPS() {
|
||||
return fipsCurvePreferences(c)
|
||||
}
|
||||
if c == nil || len(c.CurvePreferences) == 0 {
|
||||
return defaultCurvePreferences
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
// Copyright 2017 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 fipsonly restricts all TLS configuration to FIPS-approved settings.
|
||||
//
|
||||
// The effect is triggered by importing the package anywhere in a program, as in:
|
||||
//
|
||||
// import _ "crypto/tls/fipsonly"
|
||||
//
|
||||
// This package only exists in the dev.boringcrypto branch of Go.
|
||||
package fipsonly
|
||||
|
||||
// This functionality is provided as a side effect of an import to make
|
||||
// it trivial to add to an existing program. It requires only a single line
|
||||
// added to an existing source file, or it can be done by adding a whole
|
||||
// new source file and not modifying any existing source files.
|
||||
|
||||
import (
|
||||
"crypto/internal/boring/fipstls"
|
||||
"crypto/internal/boring/sig"
|
||||
)
|
||||
|
||||
func init() {
|
||||
fipstls.Force()
|
||||
sig.FIPSOnly()
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
// Copyright 2017 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 fipsonly
|
||||
|
||||
import (
|
||||
"crypto/internal/boring/fipstls"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
if !fipstls.Required() {
|
||||
t.Fatal("fipstls.Required() = false, must be true")
|
||||
}
|
||||
}
|
||||
@@ -99,11 +99,7 @@ NextCipherSuite:
|
||||
}
|
||||
|
||||
if hello.vers >= VersionTLS12 {
|
||||
hello.signatureAndHashes = supportedSignatureAlgorithms()
|
||||
}
|
||||
|
||||
if testingOnlyForceClientHelloSignatureAndHashes != nil {
|
||||
hello.signatureAndHashes = testingOnlyForceClientHelloSignatureAndHashes
|
||||
hello.signatureAndHashes = supportedSignatureAlgorithms
|
||||
}
|
||||
|
||||
var session *ClientSessionState
|
||||
@@ -289,8 +285,6 @@ func (hs *clientHandshakeState) doFullHandshake() error {
|
||||
|
||||
if !c.config.InsecureSkipVerify {
|
||||
opts := x509.VerifyOptions{
|
||||
IsBoring: isBoringCertificate,
|
||||
|
||||
Roots: c.config.RootCAs,
|
||||
CurrentTime: c.config.time(),
|
||||
DNSName: c.config.ServerName,
|
||||
|
||||
@@ -137,7 +137,7 @@ func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
|
||||
}
|
||||
}
|
||||
if rand.Intn(10) > 5 {
|
||||
m.signatureAndHashes = supportedSignatureAlgorithms()
|
||||
m.signatureAndHashes = supportedSignatureAlgorithms
|
||||
}
|
||||
m.alpnProtocols = make([]string, rand.Intn(5))
|
||||
for i := range m.alpnProtocols {
|
||||
|
||||
@@ -422,7 +422,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
|
||||
}
|
||||
if c.vers >= VersionTLS12 {
|
||||
certReq.hasSignatureAndHash = true
|
||||
certReq.signatureAndHashes = supportedSignatureAlgorithms()
|
||||
certReq.signatureAndHashes = supportedSignatureAlgorithms
|
||||
}
|
||||
|
||||
// An empty list of certificateAuthorities signals to
|
||||
@@ -526,7 +526,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
|
||||
var signatureAndHash signatureAndHash
|
||||
if certVerify.hasSignatureAndHash {
|
||||
signatureAndHash = certVerify.signatureAndHash
|
||||
if !isSupportedSignatureAndHash(signatureAndHash, supportedSignatureAlgorithms()) {
|
||||
if !isSupportedSignatureAndHash(signatureAndHash, supportedSignatureAlgorithms) {
|
||||
return errors.New("tls: unsupported hash function for client certificate")
|
||||
}
|
||||
} else {
|
||||
@@ -722,8 +722,6 @@ func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (c
|
||||
|
||||
if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 {
|
||||
opts := x509.VerifyOptions{
|
||||
IsBoring: isBoringCertificate,
|
||||
|
||||
Roots: c.config.ClientCAs,
|
||||
CurrentTime: c.config.time(),
|
||||
Intermediates: x509.NewCertPool(),
|
||||
|
||||
@@ -114,7 +114,7 @@ func md5SHA1Hash(slices [][]byte) []byte {
|
||||
// only used for >= TLS 1.2 and precisely identifies the hash function to use.
|
||||
func hashForServerKeyExchange(sigAndHash signatureAndHash, version uint16, slices ...[]byte) ([]byte, crypto.Hash, error) {
|
||||
if version >= VersionTLS12 {
|
||||
if !isSupportedSignatureAndHash(sigAndHash, supportedSignatureAlgorithms()) {
|
||||
if !isSupportedSignatureAndHash(sigAndHash, supportedSignatureAlgorithms) {
|
||||
return nil, crypto.Hash(0), errors.New("tls: unsupported hash function used by peer")
|
||||
}
|
||||
hashFunc, err := lookupTLSHash(sigAndHash.hash)
|
||||
@@ -149,7 +149,7 @@ func pickTLS12HashForSignature(sigType uint8, clientList []signatureAndHash) (ui
|
||||
if sigAndHash.signature != sigType {
|
||||
continue
|
||||
}
|
||||
if isSupportedSignatureAndHash(sigAndHash, supportedSignatureAlgorithms()) {
|
||||
if isSupportedSignatureAndHash(sigAndHash, supportedSignatureAlgorithms) {
|
||||
return sigAndHash.hash, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -319,7 +319,7 @@ func (h finishedHash) selectClientCertSignatureAlgorithm(serverList []signatureA
|
||||
}
|
||||
|
||||
for _, v := range serverList {
|
||||
if v.signature == sigType && isSupportedSignatureAndHash(v, supportedSignatureAlgorithms()) {
|
||||
if v.signature == sigType && isSupportedSignatureAndHash(v, supportedSignatureAlgorithms) {
|
||||
return v, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,11 +156,6 @@ type VerifyOptions struct {
|
||||
// constraint down the chain which mirrors Windows CryptoAPI behavior,
|
||||
// but not the spec. To accept any key usage, include ExtKeyUsageAny.
|
||||
KeyUsages []ExtKeyUsage
|
||||
|
||||
// IsBoring is a validity check for BoringCrypto.
|
||||
// If not nil, it will be called to check whether a given certificate
|
||||
// can be used for constructing verification chains.
|
||||
IsBoring func(*Certificate) bool
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -253,13 +248,6 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
|
||||
}
|
||||
}
|
||||
|
||||
if opts.IsBoring != nil && !opts.IsBoring(c) {
|
||||
// IncompatibleUsage is not quite right here,
|
||||
// but it's also the "no chains found" error
|
||||
// and is close enough.
|
||||
return CertificateInvalidError{c, IncompatibleUsage}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -848,6 +848,7 @@ type (
|
||||
TypeSpec struct {
|
||||
Doc *CommentGroup // associated documentation; or nil
|
||||
Name *Ident // type name
|
||||
Assign token.Pos // position of '=', if any
|
||||
Type Expr // *Ident, *ParenExpr, *SelectorExpr, *StarExpr, or any of the *XxxTypes
|
||||
Comment *CommentGroup // line comments; or nil
|
||||
}
|
||||
|
||||
@@ -290,7 +290,8 @@ func defaultContext() Context {
|
||||
// in all releases >= Go 1.x. Code that requires Go 1.x or later should
|
||||
// say "+build go1.x", and code that should only be built before Go 1.x
|
||||
// (perhaps it is the stub to use in that case) should say "+build !go1.x".
|
||||
c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3", "go1.4", "go1.5", "go1.6", "go1.7", "go1.8"}
|
||||
// NOTE: If you add to this list, also update the doc comment in doc.go.
|
||||
c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3", "go1.4", "go1.5", "go1.6", "go1.7", "go1.8", "go1.8.typealias"}
|
||||
|
||||
env := os.Getenv("CGO_ENABLED")
|
||||
if env == "" {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user