mirror of https://gogs.blitter.com/RLabs/xs
Updated imports and vendor/ for local fork of schwanenlied.me crypto (chacha20, newhope, kyber)
Signed-off-by: Russ Magee <rmagee@gmail.com>
This commit is contained in:
parent
d75b419c7a
commit
eb9ce0e0e2
10
go.mod
10
go.mod
|
@ -6,26 +6,24 @@ require (
|
||||||
blitter.com/go/cryptmt v1.0.0
|
blitter.com/go/cryptmt v1.0.0
|
||||||
blitter.com/go/goutmp v1.0.1
|
blitter.com/go/goutmp v1.0.1
|
||||||
blitter.com/go/herradurakex v1.0.0
|
blitter.com/go/herradurakex v1.0.0
|
||||||
|
blitter.com/go/kyber v0.0.0-20200130200857-6f2021cb88d9
|
||||||
blitter.com/go/mtwist v1.0.1 // indirect
|
blitter.com/go/mtwist v1.0.1 // indirect
|
||||||
|
blitter.com/go/newhope v0.0.0-20200130200750-192fc08a8aae
|
||||||
blitter.com/go/wanderer v0.8.1
|
blitter.com/go/wanderer v0.8.1
|
||||||
git.schwanenlied.me/yawning/chacha20.git v0.0.0-20170904085104-e3b1f968fc63 // indirect
|
|
||||||
git.schwanenlied.me/yawning/kyber.git v0.0.0-20180530164001-a270899bd22c
|
|
||||||
git.schwanenlied.me/yawning/newhope.git v0.0.0-20170622154529-9598792ba8f2
|
|
||||||
github.com/jameskeane/bcrypt v0.0.0-20120420032655-c3cd44c1e20f
|
github.com/jameskeane/bcrypt v0.0.0-20120420032655-c3cd44c1e20f
|
||||||
github.com/klauspost/cpuid v1.2.2 // indirect
|
github.com/klauspost/cpuid v1.2.2 // indirect
|
||||||
github.com/klauspost/reedsolomon v1.9.3 // indirect
|
github.com/klauspost/reedsolomon v1.9.3 // indirect
|
||||||
github.com/kr/pty v1.1.4
|
github.com/kr/pty v1.1.4
|
||||||
github.com/mattn/go-isatty v0.0.7
|
github.com/mattn/go-isatty v0.0.7
|
||||||
github.com/pkg/errors v0.8.1 // indirect
|
github.com/pkg/errors v0.8.1 // indirect
|
||||||
github.com/stretchr/testify v1.4.0 // indirect
|
|
||||||
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect
|
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect
|
||||||
github.com/templexxx/xor v0.0.0-20181023030647-4e92f724b73b // indirect
|
github.com/templexxx/xor v0.0.0-20181023030647-4e92f724b73b // indirect
|
||||||
github.com/tjfoc/gmsm v1.0.1 // indirect
|
github.com/tjfoc/gmsm v1.0.1 // indirect
|
||||||
github.com/xtaci/kcp-go v5.4.19+incompatible
|
github.com/xtaci/kcp-go v5.4.19+incompatible
|
||||||
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae // indirect
|
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae // indirect
|
||||||
golang.org/x/crypto v0.0.0-20190417174047-f416ebab96af
|
golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d
|
||||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 // indirect
|
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 // indirect
|
||||||
golang.org/x/sys v0.0.0-20190416152802-12500544f89f
|
golang.org/x/sys v0.0.0-20190902133755-9109b7679e13
|
||||||
gopkg.in/hlandau/easymetric.v1 v1.0.0 // indirect
|
gopkg.in/hlandau/easymetric.v1 v1.0.0 // indirect
|
||||||
gopkg.in/hlandau/measurable.v1 v1.0.1 // indirect
|
gopkg.in/hlandau/measurable.v1 v1.0.1 // indirect
|
||||||
gopkg.in/hlandau/passlib.v1 v1.0.10
|
gopkg.in/hlandau/passlib.v1 v1.0.10
|
||||||
|
|
13
go.sum
13
go.sum
|
@ -1,11 +1,17 @@
|
||||||
|
blitter.com/go/chacha20 v0.0.0-20200130200441-214e4085f54c h1:LcnFFg6MCIJHf26P7eOUST45fNLHJI5erq0gWZaDLCo=
|
||||||
|
blitter.com/go/chacha20 v0.0.0-20200130200441-214e4085f54c/go.mod h1:EMJtRcf22WCtHGiXCw+NB/Sb/PYcXtUgUql6LDEwyXo=
|
||||||
blitter.com/go/cryptmt v1.0.0 h1:n+cNP/ReZrNe/w5FbD8DSfv0Wpj48nxhmMoLEk4hPXs=
|
blitter.com/go/cryptmt v1.0.0 h1:n+cNP/ReZrNe/w5FbD8DSfv0Wpj48nxhmMoLEk4hPXs=
|
||||||
blitter.com/go/cryptmt v1.0.0/go.mod h1:tdME2J3O4agaDAYIYNQzzuB28yVGnPSMmV3a/ucSU84=
|
blitter.com/go/cryptmt v1.0.0/go.mod h1:tdME2J3O4agaDAYIYNQzzuB28yVGnPSMmV3a/ucSU84=
|
||||||
blitter.com/go/goutmp v1.0.1 h1:jBqtp6pDwSbF4QEC3DjNfyaS8Nv5dFCOyaTfSbbb7TU=
|
blitter.com/go/goutmp v1.0.1 h1:jBqtp6pDwSbF4QEC3DjNfyaS8Nv5dFCOyaTfSbbb7TU=
|
||||||
blitter.com/go/goutmp v1.0.1/go.mod h1:gtlbjC8xGzMk/Cf0BpnVltSa3awOqJ+B5WAxVptTMxk=
|
blitter.com/go/goutmp v1.0.1/go.mod h1:gtlbjC8xGzMk/Cf0BpnVltSa3awOqJ+B5WAxVptTMxk=
|
||||||
blitter.com/go/herradurakex v1.0.0 h1:6XaxY+JLT1HUWPF0gYJnjX3pVjrw4YhYZEzZ1U0wkyc=
|
blitter.com/go/herradurakex v1.0.0 h1:6XaxY+JLT1HUWPF0gYJnjX3pVjrw4YhYZEzZ1U0wkyc=
|
||||||
blitter.com/go/herradurakex v1.0.0/go.mod h1:m3+vYZX+2dDjdo+n/HDnXEYJX9pwmNeQLgAfJM8mtxw=
|
blitter.com/go/herradurakex v1.0.0/go.mod h1:m3+vYZX+2dDjdo+n/HDnXEYJX9pwmNeQLgAfJM8mtxw=
|
||||||
|
blitter.com/go/kyber v0.0.0-20200130200857-6f2021cb88d9 h1:D45AnrNphtvczBXRp5JQicZRTgaK/Is5bgPDDvRKhTc=
|
||||||
|
blitter.com/go/kyber v0.0.0-20200130200857-6f2021cb88d9/go.mod h1:SK6QfGG72lIfKW1Td0wH7f0wwN5nSIhV3K+wvzGNjrw=
|
||||||
blitter.com/go/mtwist v1.0.1 h1:PxmoWexfMpLmc8neHP/PcRc3s17ct7iz4d5W/qJVt04=
|
blitter.com/go/mtwist v1.0.1 h1:PxmoWexfMpLmc8neHP/PcRc3s17ct7iz4d5W/qJVt04=
|
||||||
blitter.com/go/mtwist v1.0.1/go.mod h1:aU82Nx8+b1v8oZRNqImfEDzDTPim81rY0ACKAIclV18=
|
blitter.com/go/mtwist v1.0.1/go.mod h1:aU82Nx8+b1v8oZRNqImfEDzDTPim81rY0ACKAIclV18=
|
||||||
|
blitter.com/go/newhope v0.0.0-20200130200750-192fc08a8aae h1:YBBaCcdYRrI1btsmcMTv1VMPmaSXXz0RwKOTgMJYSRU=
|
||||||
|
blitter.com/go/newhope v0.0.0-20200130200750-192fc08a8aae/go.mod h1:ywoxfDBqInPsqtnxYsmS4SYMJ5D/kNcrFgpvI+Xcun0=
|
||||||
blitter.com/go/wanderer v0.8.1 h1:oQw8yASM7iI+S8GIgf3cUFdkJ8Sy/UQxRDJqhTswgwM=
|
blitter.com/go/wanderer v0.8.1 h1:oQw8yASM7iI+S8GIgf3cUFdkJ8Sy/UQxRDJqhTswgwM=
|
||||||
blitter.com/go/wanderer v0.8.1/go.mod h1:FX1pAnZ5woEavy5CUIZco0/Gc2Msb3U0zsmi+6Hs4Rw=
|
blitter.com/go/wanderer v0.8.1/go.mod h1:FX1pAnZ5woEavy5CUIZco0/Gc2Msb3U0zsmi+6Hs4Rw=
|
||||||
git.schwanenlied.me/yawning/chacha20.git v0.0.0-20170904085104-e3b1f968fc63 h1:bwZNsbw3qFbg6ox55HrA37nPmh+/wtJxZ7uWeiAdUUc=
|
git.schwanenlied.me/yawning/chacha20.git v0.0.0-20170904085104-e3b1f968fc63 h1:bwZNsbw3qFbg6ox55HrA37nPmh+/wtJxZ7uWeiAdUUc=
|
||||||
|
@ -46,13 +52,20 @@ github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190417174047-f416ebab96af h1:6qGQw30u837TXZbCmLFR9AVA+RjJU1LIbvk0oIkDZGY=
|
golang.org/x/crypto v0.0.0-20190417174047-f416ebab96af h1:6qGQw30u837TXZbCmLFR9AVA+RjJU1LIbvk0oIkDZGY=
|
||||||
golang.org/x/crypto v0.0.0-20190417174047-f416ebab96af/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
golang.org/x/crypto v0.0.0-20190417174047-f416ebab96af/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||||
|
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d h1:9FCpayM9Egr1baVnV1SX0H87m+XB0B8S0hAMi99X/3U=
|
||||||
|
golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8=
|
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8=
|
||||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190416152802-12500544f89f h1:1ZH9RnjNgLzh6YrsRp/c6ddZ8Lq0fq9xztNOoWJ2sz4=
|
golang.org/x/sys v0.0.0-20190416152802-12500544f89f h1:1ZH9RnjNgLzh6YrsRp/c6ddZ8Lq0fq9xztNOoWJ2sz4=
|
||||||
golang.org/x/sys v0.0.0-20190416152802-12500544f89f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190416152802-12500544f89f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190902133755-9109b7679e13 h1:tdsQdquKbTNMsSZLqnLELJGzCANp9oXhu6zFBW6ODx4=
|
||||||
|
golang.org/x/sys v0.0.0-20190902133755-9109b7679e13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
|
|
@ -0,0 +1,661 @@
|
||||||
|
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 19 November 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU Affero General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works, specifically designed to ensure
|
||||||
|
cooperation with the community in the case of network server software.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
our General Public Licenses are intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
Developers that use our General Public Licenses protect your rights
|
||||||
|
with two steps: (1) assert copyright on the software, and (2) offer
|
||||||
|
you this License which gives you legal permission to copy, distribute
|
||||||
|
and/or modify the software.
|
||||||
|
|
||||||
|
A secondary benefit of defending all users' freedom is that
|
||||||
|
improvements made in alternate versions of the program, if they
|
||||||
|
receive widespread use, become available for other developers to
|
||||||
|
incorporate. Many developers of free software are heartened and
|
||||||
|
encouraged by the resulting cooperation. However, in the case of
|
||||||
|
software used on network servers, this result may fail to come about.
|
||||||
|
The GNU General Public License permits making a modified version and
|
||||||
|
letting the public access it on a server without ever releasing its
|
||||||
|
source code to the public.
|
||||||
|
|
||||||
|
The GNU Affero General Public License is designed specifically to
|
||||||
|
ensure that, in such cases, the modified source code becomes available
|
||||||
|
to the community. It requires the operator of a network server to
|
||||||
|
provide the source code of the modified version running there to the
|
||||||
|
users of that server. Therefore, public use of a modified version, on
|
||||||
|
a publicly accessible server, gives the public access to the source
|
||||||
|
code of the modified version.
|
||||||
|
|
||||||
|
An older license, called the Affero General Public License and
|
||||||
|
published by Affero, was designed to accomplish similar goals. This is
|
||||||
|
a different license, not a version of the Affero GPL, but Affero has
|
||||||
|
released a new version of the Affero GPL which permits relicensing under
|
||||||
|
this license.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, if you modify the
|
||||||
|
Program, your modified version must prominently offer all users
|
||||||
|
interacting with it remotely through a computer network (if your version
|
||||||
|
supports such interaction) an opportunity to receive the Corresponding
|
||||||
|
Source of your version by providing access to the Corresponding Source
|
||||||
|
from a network server at no charge, through some standard or customary
|
||||||
|
means of facilitating copying of software. This Corresponding Source
|
||||||
|
shall include the Corresponding Source for any work covered by version 3
|
||||||
|
of the GNU General Public License that is incorporated pursuant to the
|
||||||
|
following paragraph.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the work with which it is combined will remain governed by version
|
||||||
|
3 of the GNU General Public License.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU Affero General Public License from time to time. Such new versions
|
||||||
|
will be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU Affero General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU Affero General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU Affero General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If your software can interact with users remotely through a computer
|
||||||
|
network, you should also make sure that it provides a way for users to
|
||||||
|
get its source. For example, if your program is a web application, its
|
||||||
|
interface could display a "Source" link that leads users to an archive
|
||||||
|
of the code. There are many ways you could offer source, and different
|
||||||
|
solutions will be better for different programs; see section 13 for the
|
||||||
|
specific requirements.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
|
@ -1,7 +1,7 @@
|
||||||
### chacha20 - ChaCha20
|
### chacha20 - ChaCha20
|
||||||
#### Yawning Angel (yawning at schwanenlied dot me)
|
#### Yawning Angel (yawning at schwanenlied dot me)
|
||||||
|
|
||||||
Yet another Go ChaCha20 implementation. Everything else I found was slow,
|
Yet another Go ChaCha20 implementation. Everything else I found was slow,
|
||||||
didn't support all the variants I need to use, or relied on cgo to go fast.
|
didn't support all the variants I need to use, or relied on cgo to go fast.
|
||||||
|
|
||||||
Features:
|
Features:
|
||||||
|
@ -9,6 +9,5 @@ Features:
|
||||||
* 20 round, 256 bit key only. Everything else is pointless and stupid.
|
* 20 round, 256 bit key only. Everything else is pointless and stupid.
|
||||||
* IETF 96 bit nonce variant.
|
* IETF 96 bit nonce variant.
|
||||||
* XChaCha 24 byte nonce variant.
|
* XChaCha 24 byte nonce variant.
|
||||||
* SSE2 and AVX2 support on amd64 targets.
|
* SSSE3 and AVX2 support on amd64 targets.
|
||||||
* Incremental encrypt/decrypt support, unlike golang.org/x/crypto/salsa20.
|
* Incremental encrypt/decrypt support, unlike golang.org/x/crypto/salsa20.
|
||||||
|
|
|
@ -1,18 +1,30 @@
|
||||||
// chacha20.go - A ChaCha stream cipher implementation.
|
// Copryright (C) 2019 Yawning Angel
|
||||||
//
|
//
|
||||||
// To the extent possible under law, Yawning Angel has waived all copyright
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// and related or neighboring rights to chacha20, using the Creative
|
// it under the terms of the GNU Affero General Public License as
|
||||||
// Commons "CC0" public domain dedication. See LICENSE or
|
// published by the Free Software Foundation, either version 3 of the
|
||||||
// <http://creativecommons.org/publicdomain/zero/1.0/> for full details.
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package chacha20
|
// Package chacha20 implements the ChaCha20 stream cipher.
|
||||||
|
package chacha20 // import "blitter.com/go/chacha20"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"math"
|
"math"
|
||||||
"runtime"
|
|
||||||
|
"blitter.com/go/chacha20/internal/api"
|
||||||
|
"blitter.com/go/chacha20/internal/hardware"
|
||||||
|
"blitter.com/go/chacha20/internal/ref"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -30,41 +42,29 @@ const (
|
||||||
|
|
||||||
// HNonceSize is the HChaCha20 nonce size in bytes.
|
// HNonceSize is the HChaCha20 nonce size in bytes.
|
||||||
HNonceSize = 16
|
HNonceSize = 16
|
||||||
|
|
||||||
// BlockSize is the ChaCha20 block size in bytes.
|
|
||||||
BlockSize = 64
|
|
||||||
|
|
||||||
stateSize = 16
|
|
||||||
chachaRounds = 20
|
|
||||||
|
|
||||||
// The constant "expand 32-byte k" as little endian uint32s.
|
|
||||||
sigma0 = uint32(0x61707865)
|
|
||||||
sigma1 = uint32(0x3320646e)
|
|
||||||
sigma2 = uint32(0x79622d32)
|
|
||||||
sigma3 = uint32(0x6b206574)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrInvalidKey is the error returned when the key is invalid.
|
// ErrInvalidKey is the error returned when the key is invalid.
|
||||||
ErrInvalidKey = errors.New("key length must be KeySize bytes")
|
ErrInvalidKey = errors.New("chacha20: key length must be KeySize bytes")
|
||||||
|
|
||||||
// ErrInvalidNonce is the error returned when the nonce is invalid.
|
// ErrInvalidNonce is the error returned when the nonce is invalid.
|
||||||
ErrInvalidNonce = errors.New("nonce length must be NonceSize/INonceSize/XNonceSize bytes")
|
ErrInvalidNonce = errors.New("chacha20: nonce length must be NonceSize/INonceSize/XNonceSize bytes")
|
||||||
|
|
||||||
// ErrInvalidCounter is the error returned when the counter is invalid.
|
// ErrInvalidCounter is the error returned when the counter is invalid.
|
||||||
ErrInvalidCounter = errors.New("block counter is invalid (out of range)")
|
ErrInvalidCounter = errors.New("chacha20: block counter is invalid (out of range)")
|
||||||
|
|
||||||
useUnsafe = false
|
supportedImpls []api.Implementation
|
||||||
usingVectors = false
|
activeImpl api.Implementation
|
||||||
blocksFn = blocksRef
|
|
||||||
|
_ cipher.Stream = (*Cipher)(nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
// A Cipher is an instance of ChaCha20/XChaCha20 using a particular key and
|
// Cipher is an instance of ChaCha20/XChaCha20 using a particular key and nonce.
|
||||||
// nonce.
|
|
||||||
type Cipher struct {
|
type Cipher struct {
|
||||||
state [stateSize]uint32
|
state [api.StateSize]uint32
|
||||||
|
buf [api.BlockSize]byte
|
||||||
|
|
||||||
buf [BlockSize]byte
|
|
||||||
off int
|
off int
|
||||||
ietf bool
|
ietf bool
|
||||||
}
|
}
|
||||||
|
@ -80,6 +80,99 @@ func (c *Cipher) Reset() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Seek sets the block counter to a given offset.
|
||||||
|
func (c *Cipher) Seek(blockCounter uint64) error {
|
||||||
|
if c.ietf {
|
||||||
|
if blockCounter > math.MaxUint32 {
|
||||||
|
return ErrInvalidCounter
|
||||||
|
}
|
||||||
|
c.state[12] = uint32(blockCounter)
|
||||||
|
} else {
|
||||||
|
c.state[12] = uint32(blockCounter)
|
||||||
|
c.state[13] = uint32(blockCounter >> 32)
|
||||||
|
}
|
||||||
|
c.off = api.BlockSize
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReKey reinitializes the ChaCha20/XChaCha20 instance with the provided key
|
||||||
|
// and nonce.
|
||||||
|
func (c *Cipher) ReKey(key, nonce []byte) error {
|
||||||
|
c.Reset()
|
||||||
|
return c.doReKey(key, nonce)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cipher) doReKey(key, nonce []byte) error {
|
||||||
|
if len(key) != KeySize {
|
||||||
|
return ErrInvalidKey
|
||||||
|
}
|
||||||
|
|
||||||
|
var subKey []byte
|
||||||
|
switch len(nonce) {
|
||||||
|
case NonceSize, INonceSize:
|
||||||
|
case XNonceSize:
|
||||||
|
subKey = c.buf[:KeySize]
|
||||||
|
activeImpl.HChaCha(key, nonce, subKey)
|
||||||
|
key = subKey
|
||||||
|
nonce = nonce[16:24]
|
||||||
|
default:
|
||||||
|
return ErrInvalidNonce
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = key[31] // Force bounds check elimination.
|
||||||
|
|
||||||
|
c.state[0] = api.Sigma0
|
||||||
|
c.state[1] = api.Sigma1
|
||||||
|
c.state[2] = api.Sigma2
|
||||||
|
c.state[3] = api.Sigma3
|
||||||
|
c.state[4] = binary.LittleEndian.Uint32(key[0:4])
|
||||||
|
c.state[5] = binary.LittleEndian.Uint32(key[4:8])
|
||||||
|
c.state[6] = binary.LittleEndian.Uint32(key[8:12])
|
||||||
|
c.state[7] = binary.LittleEndian.Uint32(key[12:16])
|
||||||
|
c.state[8] = binary.LittleEndian.Uint32(key[16:20])
|
||||||
|
c.state[9] = binary.LittleEndian.Uint32(key[20:24])
|
||||||
|
c.state[10] = binary.LittleEndian.Uint32(key[24:28])
|
||||||
|
c.state[11] = binary.LittleEndian.Uint32(key[28:32])
|
||||||
|
c.state[12] = 0
|
||||||
|
if len(nonce) == INonceSize {
|
||||||
|
_ = nonce[11] // Force bounds check elimination.
|
||||||
|
c.state[13] = binary.LittleEndian.Uint32(nonce[0:4])
|
||||||
|
c.state[14] = binary.LittleEndian.Uint32(nonce[4:8])
|
||||||
|
c.state[15] = binary.LittleEndian.Uint32(nonce[8:12])
|
||||||
|
c.ietf = true
|
||||||
|
} else {
|
||||||
|
_ = nonce[7] // Force bounds check elimination.
|
||||||
|
c.state[13] = 0
|
||||||
|
c.state[14] = binary.LittleEndian.Uint32(nonce[0:4])
|
||||||
|
c.state[15] = binary.LittleEndian.Uint32(nonce[4:8])
|
||||||
|
c.ietf = false
|
||||||
|
}
|
||||||
|
c.off = api.BlockSize
|
||||||
|
|
||||||
|
if subKey != nil {
|
||||||
|
for i := range subKey {
|
||||||
|
subKey[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new ChaCha20/XChaCha20 instance.
|
||||||
|
func New(key, nonce []byte) (*Cipher, error) {
|
||||||
|
var c Cipher
|
||||||
|
if err := c.doReKey(key, nonce); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// HChaCha is the HChaCha20 hash function used to make XChaCha.
|
||||||
|
func HChaCha(key, nonce []byte, dst *[32]byte) {
|
||||||
|
activeImpl.HChaCha(key, nonce, dst[:])
|
||||||
|
}
|
||||||
|
|
||||||
// XORKeyStream sets dst to the result of XORing src with the key stream. Dst
|
// XORKeyStream sets dst to the result of XORing src with the key stream. Dst
|
||||||
// and src may be the same slice but otherwise should not overlap.
|
// and src may be the same slice but otherwise should not overlap.
|
||||||
func (c *Cipher) XORKeyStream(dst, src []byte) {
|
func (c *Cipher) XORKeyStream(dst, src []byte) {
|
||||||
|
@ -89,11 +182,11 @@ func (c *Cipher) XORKeyStream(dst, src []byte) {
|
||||||
|
|
||||||
for remaining := len(src); remaining > 0; {
|
for remaining := len(src); remaining > 0; {
|
||||||
// Process multiple blocks at once.
|
// Process multiple blocks at once.
|
||||||
if c.off == BlockSize {
|
if c.off == api.BlockSize {
|
||||||
nrBlocks := remaining / BlockSize
|
nrBlocks := remaining / api.BlockSize
|
||||||
directBytes := nrBlocks * BlockSize
|
directBytes := nrBlocks * api.BlockSize
|
||||||
if nrBlocks > 0 {
|
if nrBlocks > 0 {
|
||||||
blocksFn(&c.state, src, dst, nrBlocks, c.ietf)
|
c.doBlocks(dst, src, nrBlocks)
|
||||||
remaining -= directBytes
|
remaining -= directBytes
|
||||||
if remaining == 0 {
|
if remaining == 0 {
|
||||||
return
|
return
|
||||||
|
@ -104,37 +197,54 @@ func (c *Cipher) XORKeyStream(dst, src []byte) {
|
||||||
|
|
||||||
// If there's a partial block, generate 1 block of keystream into
|
// If there's a partial block, generate 1 block of keystream into
|
||||||
// the internal buffer.
|
// the internal buffer.
|
||||||
blocksFn(&c.state, nil, c.buf[:], 1, c.ietf)
|
c.doBlocks(c.buf[:], nil, 1)
|
||||||
c.off = 0
|
c.off = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process partial blocks from the buffered keystream.
|
// Process partial blocks from the buffered keystream.
|
||||||
toXor := BlockSize - c.off
|
toXor := api.BlockSize - c.off
|
||||||
if remaining < toXor {
|
if remaining < toXor {
|
||||||
toXor = remaining
|
toXor = remaining
|
||||||
}
|
}
|
||||||
if toXor > 0 {
|
if toXor > 0 {
|
||||||
for i, v := range src[:toXor] {
|
// The inliner doesn't want to inline this function, but my
|
||||||
dst[i] = v ^ c.buf[c.off+i]
|
// attempts to force BCE don't seem to work with manual
|
||||||
}
|
// inlining.
|
||||||
|
//
|
||||||
|
// Taking the extra function call overhead here appears to be
|
||||||
|
// worth it.
|
||||||
|
c.xorBufBytes(dst, src, toXor)
|
||||||
|
|
||||||
dst = dst[toXor:]
|
dst = dst[toXor:]
|
||||||
src = src[toXor:]
|
src = src[toXor:]
|
||||||
|
|
||||||
remaining -= toXor
|
remaining -= toXor
|
||||||
c.off += toXor
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Cipher) xorBufBytes(dst, src []byte, n int) {
|
||||||
|
// Force bounds check elimination.
|
||||||
|
buf := c.buf[c.off:]
|
||||||
|
_ = buf[n-1]
|
||||||
|
_ = dst[n-1]
|
||||||
|
_ = src[n-1]
|
||||||
|
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
dst[i] = buf[i] ^ src[i]
|
||||||
|
}
|
||||||
|
c.off += n
|
||||||
|
}
|
||||||
|
|
||||||
// KeyStream sets dst to the raw keystream.
|
// KeyStream sets dst to the raw keystream.
|
||||||
func (c *Cipher) KeyStream(dst []byte) {
|
func (c *Cipher) KeyStream(dst []byte) {
|
||||||
for remaining := len(dst); remaining > 0; {
|
for remaining := len(dst); remaining > 0; {
|
||||||
// Process multiple blocks at once.
|
// Process multiple blocks at once.
|
||||||
if c.off == BlockSize {
|
if c.off == api.BlockSize {
|
||||||
nrBlocks := remaining / BlockSize
|
nrBlocks := remaining / api.BlockSize
|
||||||
directBytes := nrBlocks * BlockSize
|
directBytes := nrBlocks * api.BlockSize
|
||||||
if nrBlocks > 0 {
|
if nrBlocks > 0 {
|
||||||
blocksFn(&c.state, nil, dst, nrBlocks, c.ietf)
|
c.doBlocks(dst, nil, nrBlocks)
|
||||||
remaining -= directBytes
|
remaining -= directBytes
|
||||||
if remaining == 0 {
|
if remaining == 0 {
|
||||||
return
|
return
|
||||||
|
@ -144,12 +254,12 @@ func (c *Cipher) KeyStream(dst []byte) {
|
||||||
|
|
||||||
// If there's a partial block, generate 1 block of keystream into
|
// If there's a partial block, generate 1 block of keystream into
|
||||||
// the internal buffer.
|
// the internal buffer.
|
||||||
blocksFn(&c.state, nil, c.buf[:], 1, c.ietf)
|
c.doBlocks(c.buf[:], nil, 1)
|
||||||
c.off = 0
|
c.off = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process partial blocks from the buffered keystream.
|
// Process partial blocks from the buffered keystream.
|
||||||
toCopy := BlockSize - c.off
|
toCopy := api.BlockSize - c.off
|
||||||
if remaining < toCopy {
|
if remaining < toCopy {
|
||||||
toCopy = remaining
|
toCopy = remaining
|
||||||
}
|
}
|
||||||
|
@ -162,112 +272,19 @@ func (c *Cipher) KeyStream(dst []byte) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReKey reinitializes the ChaCha20/XChaCha20 instance with the provided key
|
func (c *Cipher) doBlocks(dst, src []byte, nrBlocks int) {
|
||||||
// and nonce.
|
|
||||||
func (c *Cipher) ReKey(key, nonce []byte) error {
|
|
||||||
if len(key) != KeySize {
|
|
||||||
return ErrInvalidKey
|
|
||||||
}
|
|
||||||
|
|
||||||
switch len(nonce) {
|
|
||||||
case NonceSize:
|
|
||||||
case INonceSize:
|
|
||||||
case XNonceSize:
|
|
||||||
var subkey [KeySize]byte
|
|
||||||
var subnonce [HNonceSize]byte
|
|
||||||
copy(subnonce[:], nonce[0:16])
|
|
||||||
HChaCha(key, &subnonce, &subkey)
|
|
||||||
key = subkey[:]
|
|
||||||
nonce = nonce[16:24]
|
|
||||||
defer func() {
|
|
||||||
for i := range subkey {
|
|
||||||
subkey[i] = 0
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
default:
|
|
||||||
return ErrInvalidNonce
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Reset()
|
|
||||||
c.state[0] = sigma0
|
|
||||||
c.state[1] = sigma1
|
|
||||||
c.state[2] = sigma2
|
|
||||||
c.state[3] = sigma3
|
|
||||||
c.state[4] = binary.LittleEndian.Uint32(key[0:4])
|
|
||||||
c.state[5] = binary.LittleEndian.Uint32(key[4:8])
|
|
||||||
c.state[6] = binary.LittleEndian.Uint32(key[8:12])
|
|
||||||
c.state[7] = binary.LittleEndian.Uint32(key[12:16])
|
|
||||||
c.state[8] = binary.LittleEndian.Uint32(key[16:20])
|
|
||||||
c.state[9] = binary.LittleEndian.Uint32(key[20:24])
|
|
||||||
c.state[10] = binary.LittleEndian.Uint32(key[24:28])
|
|
||||||
c.state[11] = binary.LittleEndian.Uint32(key[28:32])
|
|
||||||
c.state[12] = 0
|
|
||||||
if len(nonce) == INonceSize {
|
|
||||||
c.state[13] = binary.LittleEndian.Uint32(nonce[0:4])
|
|
||||||
c.state[14] = binary.LittleEndian.Uint32(nonce[4:8])
|
|
||||||
c.state[15] = binary.LittleEndian.Uint32(nonce[8:12])
|
|
||||||
c.ietf = true
|
|
||||||
} else {
|
|
||||||
c.state[13] = 0
|
|
||||||
c.state[14] = binary.LittleEndian.Uint32(nonce[0:4])
|
|
||||||
c.state[15] = binary.LittleEndian.Uint32(nonce[4:8])
|
|
||||||
c.ietf = false
|
|
||||||
}
|
|
||||||
c.off = BlockSize
|
|
||||||
return nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Seek sets the block counter to a given offset.
|
|
||||||
func (c *Cipher) Seek(blockCounter uint64) error {
|
|
||||||
if c.ietf {
|
if c.ietf {
|
||||||
if blockCounter > math.MaxUint32 {
|
ctr := uint64(c.state[12])
|
||||||
return ErrInvalidCounter
|
if ctr+uint64(nrBlocks) > math.MaxUint32 {
|
||||||
|
panic("chacha20: will exceed key stream per nonce limit")
|
||||||
}
|
}
|
||||||
c.state[12] = uint32(blockCounter)
|
|
||||||
} else {
|
|
||||||
c.state[12] = uint32(blockCounter)
|
|
||||||
c.state[13] = uint32(blockCounter >> 32)
|
|
||||||
}
|
}
|
||||||
c.off = BlockSize
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewCipher returns a new ChaCha20/XChaCha20 instance.
|
activeImpl.Blocks(&c.state, dst, src, nrBlocks)
|
||||||
func NewCipher(key, nonce []byte) (*Cipher, error) {
|
|
||||||
c := new(Cipher)
|
|
||||||
if err := c.ReKey(key, nonce); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// HChaCha is the HChaCha20 hash function used to make XChaCha.
|
|
||||||
func HChaCha(key []byte, nonce *[HNonceSize]byte, out *[32]byte) {
|
|
||||||
var x [stateSize]uint32 // Last 4 slots unused, sigma hardcoded.
|
|
||||||
x[0] = binary.LittleEndian.Uint32(key[0:4])
|
|
||||||
x[1] = binary.LittleEndian.Uint32(key[4:8])
|
|
||||||
x[2] = binary.LittleEndian.Uint32(key[8:12])
|
|
||||||
x[3] = binary.LittleEndian.Uint32(key[12:16])
|
|
||||||
x[4] = binary.LittleEndian.Uint32(key[16:20])
|
|
||||||
x[5] = binary.LittleEndian.Uint32(key[20:24])
|
|
||||||
x[6] = binary.LittleEndian.Uint32(key[24:28])
|
|
||||||
x[7] = binary.LittleEndian.Uint32(key[28:32])
|
|
||||||
x[8] = binary.LittleEndian.Uint32(nonce[0:4])
|
|
||||||
x[9] = binary.LittleEndian.Uint32(nonce[4:8])
|
|
||||||
x[10] = binary.LittleEndian.Uint32(nonce[8:12])
|
|
||||||
x[11] = binary.LittleEndian.Uint32(nonce[12:16])
|
|
||||||
hChaChaRef(&x, out)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
switch runtime.GOARCH {
|
supportedImpls = hardware.Register(supportedImpls)
|
||||||
case "386", "amd64":
|
supportedImpls = ref.Register(supportedImpls)
|
||||||
// Abuse unsafe to skip calling binary.LittleEndian.PutUint32
|
activeImpl = supportedImpls[0]
|
||||||
// in the critical path. This is a big boost on systems that are
|
|
||||||
// little endian and not overly picky about alignment.
|
|
||||||
useUnsafe = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ cipher.Stream = (*Cipher)(nil)
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
module blitter.com/go/chacha20
|
||||||
|
|
||||||
|
go 1.12
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/stretchr/testify v1.4.0
|
||||||
|
golang.org/x/sys v0.0.0-20190902133755-9109b7679e13
|
||||||
|
)
|
|
@ -0,0 +1,12 @@
|
||||||
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
golang.org/x/sys v0.0.0-20190902133755-9109b7679e13 h1:tdsQdquKbTNMsSZLqnLELJGzCANp9oXhu6zFBW6ODx4=
|
||||||
|
golang.org/x/sys v0.0.0-20190902133755-9109b7679e13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
@ -0,0 +1,59 @@
|
||||||
|
// Copryright (C) 2019 Yawning Angel
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as
|
||||||
|
// published by the Free Software Foundation, either version 3 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
// Package api provides the ChaCha20 implementation abstract interface.
|
||||||
|
package api
|
||||||
|
|
||||||
|
const (
|
||||||
|
// BlockSize is the size of a ChaCha20 block in bytes.
|
||||||
|
BlockSize = 64
|
||||||
|
|
||||||
|
// StateSize is the size of the ChaCha20 state as 32 bit unsigned words.
|
||||||
|
StateSize = 16
|
||||||
|
|
||||||
|
// HashSize is the size of the HChaCha output in bytes.
|
||||||
|
HashSize = 32
|
||||||
|
|
||||||
|
// HNonceSize is the HChaCha20 nonce size in bytes.
|
||||||
|
HNonceSize = 16
|
||||||
|
|
||||||
|
// Sigma0 is the first word of the ChaCha constant.
|
||||||
|
Sigma0 = uint32(0x61707865)
|
||||||
|
|
||||||
|
// Sigma1 is the second word of the ChaCha constant.
|
||||||
|
Sigma1 = uint32(0x3320646e)
|
||||||
|
|
||||||
|
// Sigma2 is the third word of the ChaCha constant.
|
||||||
|
Sigma2 = uint32(0x79622d32)
|
||||||
|
|
||||||
|
// Sigma3 is the fourth word of the ChaCha constant.
|
||||||
|
Sigma3 = uint32(0x6b206574)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Implementation is a ChaCha20 implementation
|
||||||
|
type Implementation interface {
|
||||||
|
// Name returns the name of the implementation.
|
||||||
|
Name() string
|
||||||
|
|
||||||
|
// Blocks calculates the ChaCha20 blocks. If src is not nil, dst will
|
||||||
|
// be set to the XOR of src with the key stream, otherwise dst will be
|
||||||
|
// set to the key stream.
|
||||||
|
Blocks(x *[StateSize]uint32, dst, src []byte, nrBlocks int)
|
||||||
|
|
||||||
|
// HChaCha calculates the HChaCha20 hash.
|
||||||
|
//
|
||||||
|
// Note: `dst` is guaranteed to be HashSize bytes.
|
||||||
|
HChaCha(key, nonce []byte, dst []byte)
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
// Copryright (C) 2019 Yawning Angel
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as
|
||||||
|
// published by the Free Software Foundation, either version 3 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
// Package hardware provides the hardware accelerated ChaCha20 implementations.
|
||||||
|
package hardware
|
||||||
|
|
||||||
|
import "blitter.com/go/chacha20/internal/api"
|
||||||
|
|
||||||
|
var hardwareImpls []api.Implementation
|
||||||
|
|
||||||
|
// Register appends the implementation(s) to the provided slice, and returns the
|
||||||
|
// new slice.
|
||||||
|
func Register(impls []api.Implementation) []api.Implementation {
|
||||||
|
return append(impls, hardwareImpls...)
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
// Copryright (C) 2019 Yawning Angel
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as
|
||||||
|
// published by the Free Software Foundation, either version 3 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
// +build amd64,!noasm
|
||||||
|
|
||||||
|
package hardware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"golang.org/x/sys/cpu"
|
||||||
|
|
||||||
|
"blitter.com/go/chacha20/internal/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func blocksAVX2(s *[api.StateSize]uint32, in, out []byte)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func hChaChaAVX2(key, nonce []byte, dst *byte)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func blocksSSSE3(s *[api.StateSize]uint32, in, out []byte)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func hChaChaSSSE3(key, nonce []byte, dst *byte)
|
||||||
|
|
||||||
|
type implAmd64 struct {
|
||||||
|
name string
|
||||||
|
|
||||||
|
blocksFn func(*[api.StateSize]uint32, []byte, []byte, int)
|
||||||
|
hChaChaFn func([]byte, []byte, *byte)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (impl *implAmd64) Name() string {
|
||||||
|
return impl.name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (impl *implAmd64) Blocks(x *[api.StateSize]uint32, dst, src []byte, nrBlocks int) {
|
||||||
|
impl.blocksFn(x, dst, src, nrBlocks)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (impl *implAmd64) HChaCha(key, nonce []byte, dst []byte) {
|
||||||
|
impl.hChaChaFn(key, nonce, &dst[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
func blockWrapper(fn func(*[api.StateSize]uint32, []byte, []byte)) func(*[api.StateSize]uint32, []byte, []byte, int) {
|
||||||
|
return func(x *[api.StateSize]uint32, dst, src []byte, nrBlocks int) {
|
||||||
|
sz := nrBlocks * api.BlockSize
|
||||||
|
if src != nil {
|
||||||
|
fn(x, src[:sz], dst[:sz])
|
||||||
|
} else {
|
||||||
|
// Sub-optimal, but the compiler special cases this to an assembly
|
||||||
|
// optimized runtime.memclrNoHeapPointers, so it's not terrible.
|
||||||
|
for i := range dst[:sz] {
|
||||||
|
dst[i] = 0
|
||||||
|
}
|
||||||
|
fn(x, dst[:sz], dst[:sz])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
if cpu.X86.HasAVX2 {
|
||||||
|
hardwareImpls = append(hardwareImpls, &implAmd64{
|
||||||
|
name: "amd64_avx2",
|
||||||
|
blocksFn: blockWrapper(blocksAVX2),
|
||||||
|
hChaChaFn: hChaChaAVX2,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if cpu.X86.HasSSE3 {
|
||||||
|
hardwareImpls = append(hardwareImpls, &implAmd64{
|
||||||
|
name: "amd64_ssse3",
|
||||||
|
blocksFn: blockWrapper(blocksSSSE3),
|
||||||
|
hChaChaFn: hChaChaSSSE3,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,374 @@
|
||||||
|
// Copryright (C) 2019 Yawning Angel
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as
|
||||||
|
// published by the Free Software Foundation, either version 3 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
// Package ref provides the portable ChaCha20 implementation.
|
||||||
|
package ref
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"math/bits"
|
||||||
|
|
||||||
|
"blitter.com/go/chacha20/internal/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
const rounds = 20
|
||||||
|
|
||||||
|
// Impl is the reference implementation (exposed for testing).
|
||||||
|
var Impl = &implRef{}
|
||||||
|
|
||||||
|
type implRef struct{}
|
||||||
|
|
||||||
|
func (impl *implRef) Name() string {
|
||||||
|
return "ref"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (impl *implRef) Blocks(x *[api.StateSize]uint32, dst, src []byte, nrBlocks int) {
|
||||||
|
for n := 0; n < nrBlocks; n++ {
|
||||||
|
x0, x1, x2, x3 := api.Sigma0, api.Sigma1, api.Sigma2, api.Sigma3
|
||||||
|
x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 := x[4], x[5], x[6], x[7], x[8], x[9], x[10], x[11], x[12], x[13], x[14], x[15]
|
||||||
|
|
||||||
|
for i := rounds; i > 0; i -= 2 {
|
||||||
|
// quarterround(x, 0, 4, 8, 12)
|
||||||
|
x0 += x4
|
||||||
|
x12 ^= x0
|
||||||
|
x12 = bits.RotateLeft32(x12, 16)
|
||||||
|
x8 += x12
|
||||||
|
x4 ^= x8
|
||||||
|
x4 = bits.RotateLeft32(x4, 12)
|
||||||
|
x0 += x4
|
||||||
|
x12 ^= x0
|
||||||
|
x12 = bits.RotateLeft32(x12, 8)
|
||||||
|
x8 += x12
|
||||||
|
x4 ^= x8
|
||||||
|
x4 = bits.RotateLeft32(x4, 7)
|
||||||
|
|
||||||
|
// quarterround(x, 1, 5, 9, 13)
|
||||||
|
x1 += x5
|
||||||
|
x13 ^= x1
|
||||||
|
x13 = bits.RotateLeft32(x13, 16)
|
||||||
|
x9 += x13
|
||||||
|
x5 ^= x9
|
||||||
|
x5 = bits.RotateLeft32(x5, 12)
|
||||||
|
x1 += x5
|
||||||
|
x13 ^= x1
|
||||||
|
x13 = bits.RotateLeft32(x13, 8)
|
||||||
|
x9 += x13
|
||||||
|
x5 ^= x9
|
||||||
|
x5 = bits.RotateLeft32(x5, 7)
|
||||||
|
|
||||||
|
// quarterround(x, 2, 6, 10, 14)
|
||||||
|
x2 += x6
|
||||||
|
x14 ^= x2
|
||||||
|
x14 = bits.RotateLeft32(x14, 16)
|
||||||
|
x10 += x14
|
||||||
|
x6 ^= x10
|
||||||
|
x6 = bits.RotateLeft32(x6, 12)
|
||||||
|
x2 += x6
|
||||||
|
x14 ^= x2
|
||||||
|
x14 = bits.RotateLeft32(x14, 8)
|
||||||
|
x10 += x14
|
||||||
|
x6 ^= x10
|
||||||
|
x6 = bits.RotateLeft32(x6, 7)
|
||||||
|
|
||||||
|
// quarterround(x, 3, 7, 11, 15)
|
||||||
|
x3 += x7
|
||||||
|
x15 ^= x3
|
||||||
|
x15 = bits.RotateLeft32(x15, 16)
|
||||||
|
x11 += x15
|
||||||
|
x7 ^= x11
|
||||||
|
x7 = bits.RotateLeft32(x7, 12)
|
||||||
|
x3 += x7
|
||||||
|
x15 ^= x3
|
||||||
|
x15 = bits.RotateLeft32(x15, 8)
|
||||||
|
x11 += x15
|
||||||
|
x7 ^= x11
|
||||||
|
x7 = bits.RotateLeft32(x7, 7)
|
||||||
|
|
||||||
|
// quarterround(x, 0, 5, 10, 15)
|
||||||
|
x0 += x5
|
||||||
|
x15 ^= x0
|
||||||
|
x15 = bits.RotateLeft32(x15, 16)
|
||||||
|
x10 += x15
|
||||||
|
x5 ^= x10
|
||||||
|
x5 = bits.RotateLeft32(x5, 12)
|
||||||
|
x0 += x5
|
||||||
|
x15 ^= x0
|
||||||
|
x15 = bits.RotateLeft32(x15, 8)
|
||||||
|
x10 += x15
|
||||||
|
x5 ^= x10
|
||||||
|
x5 = bits.RotateLeft32(x5, 7)
|
||||||
|
|
||||||
|
// quarterround(x, 1, 6, 11, 12)
|
||||||
|
x1 += x6
|
||||||
|
x12 ^= x1
|
||||||
|
x12 = bits.RotateLeft32(x12, 16)
|
||||||
|
x11 += x12
|
||||||
|
x6 ^= x11
|
||||||
|
x6 = bits.RotateLeft32(x6, 12)
|
||||||
|
x1 += x6
|
||||||
|
x12 ^= x1
|
||||||
|
x12 = bits.RotateLeft32(x12, 8)
|
||||||
|
x11 += x12
|
||||||
|
x6 ^= x11
|
||||||
|
x6 = bits.RotateLeft32(x6, 7)
|
||||||
|
|
||||||
|
// quarterround(x, 2, 7, 8, 13)
|
||||||
|
x2 += x7
|
||||||
|
x13 ^= x2
|
||||||
|
x13 = bits.RotateLeft32(x13, 16)
|
||||||
|
x8 += x13
|
||||||
|
x7 ^= x8
|
||||||
|
x7 = bits.RotateLeft32(x7, 12)
|
||||||
|
x2 += x7
|
||||||
|
x13 ^= x2
|
||||||
|
x13 = bits.RotateLeft32(x13, 8)
|
||||||
|
x8 += x13
|
||||||
|
x7 ^= x8
|
||||||
|
x7 = bits.RotateLeft32(x7, 7)
|
||||||
|
|
||||||
|
// quarterround(x, 3, 4, 9, 14)
|
||||||
|
x3 += x4
|
||||||
|
x14 ^= x3
|
||||||
|
x14 = bits.RotateLeft32(x14, 16)
|
||||||
|
x9 += x14
|
||||||
|
x4 ^= x9
|
||||||
|
x4 = bits.RotateLeft32(x4, 12)
|
||||||
|
x3 += x4
|
||||||
|
x14 ^= x3
|
||||||
|
x14 = bits.RotateLeft32(x14, 8)
|
||||||
|
x9 += x14
|
||||||
|
x4 ^= x9
|
||||||
|
x4 = bits.RotateLeft32(x4, 7)
|
||||||
|
}
|
||||||
|
|
||||||
|
x0 += api.Sigma0
|
||||||
|
x1 += api.Sigma1
|
||||||
|
x2 += api.Sigma2
|
||||||
|
x3 += api.Sigma3
|
||||||
|
x4 += x[4]
|
||||||
|
x5 += x[5]
|
||||||
|
x6 += x[6]
|
||||||
|
x7 += x[7]
|
||||||
|
x8 += x[8]
|
||||||
|
x9 += x[9]
|
||||||
|
x10 += x[10]
|
||||||
|
x11 += x[11]
|
||||||
|
x12 += x[12]
|
||||||
|
x13 += x[13]
|
||||||
|
x14 += x[14]
|
||||||
|
x15 += x[15]
|
||||||
|
|
||||||
|
_ = dst[api.BlockSize-1] // Force bounds check elimination.
|
||||||
|
|
||||||
|
if src != nil {
|
||||||
|
_ = src[api.BlockSize-1] // Force bounds check elimination.
|
||||||
|
binary.LittleEndian.PutUint32(dst[0:4], binary.LittleEndian.Uint32(src[0:4])^x0)
|
||||||
|
binary.LittleEndian.PutUint32(dst[4:8], binary.LittleEndian.Uint32(src[4:8])^x1)
|
||||||
|
binary.LittleEndian.PutUint32(dst[8:12], binary.LittleEndian.Uint32(src[8:12])^x2)
|
||||||
|
binary.LittleEndian.PutUint32(dst[12:16], binary.LittleEndian.Uint32(src[12:16])^x3)
|
||||||
|
binary.LittleEndian.PutUint32(dst[16:20], binary.LittleEndian.Uint32(src[16:20])^x4)
|
||||||
|
binary.LittleEndian.PutUint32(dst[20:24], binary.LittleEndian.Uint32(src[20:24])^x5)
|
||||||
|
binary.LittleEndian.PutUint32(dst[24:28], binary.LittleEndian.Uint32(src[24:28])^x6)
|
||||||
|
binary.LittleEndian.PutUint32(dst[28:32], binary.LittleEndian.Uint32(src[28:32])^x7)
|
||||||
|
binary.LittleEndian.PutUint32(dst[32:36], binary.LittleEndian.Uint32(src[32:36])^x8)
|
||||||
|
binary.LittleEndian.PutUint32(dst[36:40], binary.LittleEndian.Uint32(src[36:40])^x9)
|
||||||
|
binary.LittleEndian.PutUint32(dst[40:44], binary.LittleEndian.Uint32(src[40:44])^x10)
|
||||||
|
binary.LittleEndian.PutUint32(dst[44:48], binary.LittleEndian.Uint32(src[44:48])^x11)
|
||||||
|
binary.LittleEndian.PutUint32(dst[48:52], binary.LittleEndian.Uint32(src[48:52])^x12)
|
||||||
|
binary.LittleEndian.PutUint32(dst[52:56], binary.LittleEndian.Uint32(src[52:56])^x13)
|
||||||
|
binary.LittleEndian.PutUint32(dst[56:60], binary.LittleEndian.Uint32(src[56:60])^x14)
|
||||||
|
binary.LittleEndian.PutUint32(dst[60:64], binary.LittleEndian.Uint32(src[60:64])^x15)
|
||||||
|
src = src[api.BlockSize:]
|
||||||
|
} else {
|
||||||
|
binary.LittleEndian.PutUint32(dst[0:4], x0)
|
||||||
|
binary.LittleEndian.PutUint32(dst[4:8], x1)
|
||||||
|
binary.LittleEndian.PutUint32(dst[8:12], x2)
|
||||||
|
binary.LittleEndian.PutUint32(dst[12:16], x3)
|
||||||
|
binary.LittleEndian.PutUint32(dst[16:20], x4)
|
||||||
|
binary.LittleEndian.PutUint32(dst[20:24], x5)
|
||||||
|
binary.LittleEndian.PutUint32(dst[24:28], x6)
|
||||||
|
binary.LittleEndian.PutUint32(dst[28:32], x7)
|
||||||
|
binary.LittleEndian.PutUint32(dst[32:36], x8)
|
||||||
|
binary.LittleEndian.PutUint32(dst[36:40], x9)
|
||||||
|
binary.LittleEndian.PutUint32(dst[40:44], x10)
|
||||||
|
binary.LittleEndian.PutUint32(dst[44:48], x11)
|
||||||
|
binary.LittleEndian.PutUint32(dst[48:52], x12)
|
||||||
|
binary.LittleEndian.PutUint32(dst[52:56], x13)
|
||||||
|
binary.LittleEndian.PutUint32(dst[56:60], x14)
|
||||||
|
binary.LittleEndian.PutUint32(dst[60:64], x15)
|
||||||
|
}
|
||||||
|
dst = dst[api.BlockSize:]
|
||||||
|
|
||||||
|
// Stoping at 2^70 bytes per nonce is the user's responsibility.
|
||||||
|
ctr := uint64(x[13])<<32 | uint64(x[12])
|
||||||
|
ctr++
|
||||||
|
x[12] = uint32(ctr)
|
||||||
|
x[13] = uint32(ctr >> 32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (impl *implRef) HChaCha(key, nonce []byte, dst []byte) {
|
||||||
|
// Force bounds check elimination.
|
||||||
|
_ = key[31]
|
||||||
|
_ = nonce[api.HNonceSize-1]
|
||||||
|
|
||||||
|
x0, x1, x2, x3 := api.Sigma0, api.Sigma1, api.Sigma2, api.Sigma3
|
||||||
|
x4 := binary.LittleEndian.Uint32(key[0:4])
|
||||||
|
x5 := binary.LittleEndian.Uint32(key[4:8])
|
||||||
|
x6 := binary.LittleEndian.Uint32(key[8:12])
|
||||||
|
x7 := binary.LittleEndian.Uint32(key[12:16])
|
||||||
|
x8 := binary.LittleEndian.Uint32(key[16:20])
|
||||||
|
x9 := binary.LittleEndian.Uint32(key[20:24])
|
||||||
|
x10 := binary.LittleEndian.Uint32(key[24:28])
|
||||||
|
x11 := binary.LittleEndian.Uint32(key[28:32])
|
||||||
|
x12 := binary.LittleEndian.Uint32(nonce[0:4])
|
||||||
|
x13 := binary.LittleEndian.Uint32(nonce[4:8])
|
||||||
|
x14 := binary.LittleEndian.Uint32(nonce[8:12])
|
||||||
|
x15 := binary.LittleEndian.Uint32(nonce[12:16])
|
||||||
|
|
||||||
|
// Yes, this could be carved out into a function for code reuse (TM)
|
||||||
|
// however the go inliner won't inline it.
|
||||||
|
for i := rounds; i > 0; i -= 2 {
|
||||||
|
// quarterround(x, 0, 4, 8, 12)
|
||||||
|
x0 += x4
|
||||||
|
x12 ^= x0
|
||||||
|
x12 = bits.RotateLeft32(x12, 16)
|
||||||
|
x8 += x12
|
||||||
|
x4 ^= x8
|
||||||
|
x4 = bits.RotateLeft32(x4, 12)
|
||||||
|
x0 += x4
|
||||||
|
x12 ^= x0
|
||||||
|
x12 = bits.RotateLeft32(x12, 8)
|
||||||
|
x8 += x12
|
||||||
|
x4 ^= x8
|
||||||
|
x4 = bits.RotateLeft32(x4, 7)
|
||||||
|
|
||||||
|
// quarterround(x, 1, 5, 9, 13)
|
||||||
|
x1 += x5
|
||||||
|
x13 ^= x1
|
||||||
|
x13 = bits.RotateLeft32(x13, 16)
|
||||||
|
x9 += x13
|
||||||
|
x5 ^= x9
|
||||||
|
x5 = bits.RotateLeft32(x5, 12)
|
||||||
|
x1 += x5
|
||||||
|
x13 ^= x1
|
||||||
|
x13 = bits.RotateLeft32(x13, 8)
|
||||||
|
x9 += x13
|
||||||
|
x5 ^= x9
|
||||||
|
x5 = bits.RotateLeft32(x5, 7)
|
||||||
|
|
||||||
|
// quarterround(x, 2, 6, 10, 14)
|
||||||
|
x2 += x6
|
||||||
|
x14 ^= x2
|
||||||
|
x14 = bits.RotateLeft32(x14, 16)
|
||||||
|
x10 += x14
|
||||||
|
x6 ^= x10
|
||||||
|
x6 = bits.RotateLeft32(x6, 12)
|
||||||
|
x2 += x6
|
||||||
|
x14 ^= x2
|
||||||
|
x14 = bits.RotateLeft32(x14, 8)
|
||||||
|
x10 += x14
|
||||||
|
x6 ^= x10
|
||||||
|
x6 = bits.RotateLeft32(x6, 7)
|
||||||
|
|
||||||
|
// quarterround(x, 3, 7, 11, 15)
|
||||||
|
x3 += x7
|
||||||
|
x15 ^= x3
|
||||||
|
x15 = bits.RotateLeft32(x15, 16)
|
||||||
|
x11 += x15
|
||||||
|
x7 ^= x11
|
||||||
|
x7 = bits.RotateLeft32(x7, 12)
|
||||||
|
x3 += x7
|
||||||
|
x15 ^= x3
|
||||||
|
x15 = bits.RotateLeft32(x15, 8)
|
||||||
|
x11 += x15
|
||||||
|
x7 ^= x11
|
||||||
|
x7 = bits.RotateLeft32(x7, 7)
|
||||||
|
|
||||||
|
// quarterround(x, 0, 5, 10, 15)
|
||||||
|
x0 += x5
|
||||||
|
x15 ^= x0
|
||||||
|
x15 = bits.RotateLeft32(x15, 16)
|
||||||
|
x10 += x15
|
||||||
|
x5 ^= x10
|
||||||
|
x5 = bits.RotateLeft32(x5, 12)
|
||||||
|
x0 += x5
|
||||||
|
x15 ^= x0
|
||||||
|
x15 = bits.RotateLeft32(x15, 8)
|
||||||
|
x10 += x15
|
||||||
|
x5 ^= x10
|
||||||
|
x5 = bits.RotateLeft32(x5, 7)
|
||||||
|
|
||||||
|
// quarterround(x, 1, 6, 11, 12)
|
||||||
|
x1 += x6
|
||||||
|
x12 ^= x1
|
||||||
|
x12 = bits.RotateLeft32(x12, 16)
|
||||||
|
x11 += x12
|
||||||
|
x6 ^= x11
|
||||||
|
x6 = bits.RotateLeft32(x6, 12)
|
||||||
|
x1 += x6
|
||||||
|
x12 ^= x1
|
||||||
|
x12 = bits.RotateLeft32(x12, 8)
|
||||||
|
x11 += x12
|
||||||
|
x6 ^= x11
|
||||||
|
x6 = bits.RotateLeft32(x6, 7)
|
||||||
|
|
||||||
|
// quarterround(x, 2, 7, 8, 13)
|
||||||
|
x2 += x7
|
||||||
|
x13 ^= x2
|
||||||
|
x13 = bits.RotateLeft32(x13, 16)
|
||||||
|
x8 += x13
|
||||||
|
x7 ^= x8
|
||||||
|
x7 = bits.RotateLeft32(x7, 12)
|
||||||
|
x2 += x7
|
||||||
|
x13 ^= x2
|
||||||
|
x13 = bits.RotateLeft32(x13, 8)
|
||||||
|
x8 += x13
|
||||||
|
x7 ^= x8
|
||||||
|
x7 = bits.RotateLeft32(x7, 7)
|
||||||
|
|
||||||
|
// quarterround(x, 3, 4, 9, 14)
|
||||||
|
x3 += x4
|
||||||
|
x14 ^= x3
|
||||||
|
x14 = bits.RotateLeft32(x14, 16)
|
||||||
|
x9 += x14
|
||||||
|
x4 ^= x9
|
||||||
|
x4 = bits.RotateLeft32(x4, 12)
|
||||||
|
x3 += x4
|
||||||
|
x14 ^= x3
|
||||||
|
x14 = bits.RotateLeft32(x14, 8)
|
||||||
|
x9 += x14
|
||||||
|
x4 ^= x9
|
||||||
|
x4 = bits.RotateLeft32(x4, 7)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HChaCha returns x0...x3 | x12...x15, which corresponds to the
|
||||||
|
// indexes of the ChaCha constant and the indexes of the IV.
|
||||||
|
_ = dst[api.HashSize-1] // Force bounds check elimination.
|
||||||
|
binary.LittleEndian.PutUint32(dst[0:4], x0)
|
||||||
|
binary.LittleEndian.PutUint32(dst[4:8], x1)
|
||||||
|
binary.LittleEndian.PutUint32(dst[8:12], x2)
|
||||||
|
binary.LittleEndian.PutUint32(dst[12:16], x3)
|
||||||
|
binary.LittleEndian.PutUint32(dst[16:20], x12)
|
||||||
|
binary.LittleEndian.PutUint32(dst[20:24], x13)
|
||||||
|
binary.LittleEndian.PutUint32(dst[24:28], x14)
|
||||||
|
binary.LittleEndian.PutUint32(dst[28:32], x15)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register appends the implementation to the provided slice, and returns the
|
||||||
|
// new slice.
|
||||||
|
func Register(impls []api.Implementation) []api.Implementation {
|
||||||
|
return append(impls, Impl)
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
module blitter.com/go/kyber
|
||||||
|
|
||||||
|
go 1.12
|
||||||
|
|
||||||
|
require golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d
|
|
@ -0,0 +1,7 @@
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d h1:9FCpayM9Egr1baVnV1SX0H87m+XB0B8S0hAMi99X/3U=
|
||||||
|
golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
package newhope
|
package newhope
|
||||||
|
|
||||||
import "git.schwanenlied.me/yawning/chacha20.git"
|
import "blitter.com/go/chacha20"
|
||||||
|
|
||||||
func abs(v int32) int32 {
|
func abs(v int32) int32 {
|
||||||
mask := v >> 31
|
mask := v >> 31
|
||||||
|
@ -73,7 +73,7 @@ func (c *poly) helpRec(v *poly, seed *[SeedBytes]byte, nonce byte) {
|
||||||
|
|
||||||
n[7] = nonce
|
n[7] = nonce
|
||||||
|
|
||||||
stream, err := chacha20.NewCipher(seed[:], n[:])
|
stream, err := chacha20.New(seed[:], n[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
module blitter.com/go/newhope
|
||||||
|
|
||||||
|
go 1.12
|
||||||
|
|
||||||
|
require (
|
||||||
|
blitter.com/go/chacha20 v0.0.0-20200130200441-214e4085f54c
|
||||||
|
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472
|
||||||
|
)
|
|
@ -0,0 +1,19 @@
|
||||||
|
blitter.com/go/chacha20 v0.0.0-20200130200441-214e4085f54c h1:LcnFFg6MCIJHf26P7eOUST45fNLHJI5erq0gWZaDLCo=
|
||||||
|
blitter.com/go/chacha20 v0.0.0-20200130200441-214e4085f54c/go.mod h1:EMJtRcf22WCtHGiXCw+NB/Sb/PYcXtUgUql6LDEwyXo=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
gitlab.com/yawning/chacha20.git v0.0.0-20190902183103-644b09ac4e6e h1:QhupcTDYYRrhIY0f5Ad5v/nU8lJWjzzN6qQu1ndOm0c=
|
||||||
|
gitlab.com/yawning/chacha20.git v0.0.0-20190902183103-644b09ac4e6e/go.mod h1:3x6b94nWCP/a2XB/joOPMiGYUBvqbLfeY/BkHLeDs6s=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 h1:Gv7RPwsi3eZ2Fgewe3CBsuOebPwO27PoXzRpJPsvSSM=
|
||||||
|
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190902133755-9109b7679e13 h1:tdsQdquKbTNMsSZLqnLELJGzCANp9oXhu6zFBW6ODx4=
|
||||||
|
golang.org/x/sys v0.0.0-20190902133755-9109b7679e13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
@ -10,7 +10,7 @@ package newhope
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
|
||||||
"git.schwanenlied.me/yawning/chacha20.git"
|
"blitter.com/go/chacha20"
|
||||||
"golang.org/x/crypto/sha3"
|
"golang.org/x/crypto/sha3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -115,8 +115,8 @@ func (p *poly) uniform(seed *[SeedBytes]byte, torSampling bool) {
|
||||||
|
|
||||||
// h and buf are left unscrubbed because the output is public.
|
// h and buf are left unscrubbed because the output is public.
|
||||||
h := sha3.NewShake128()
|
h := sha3.NewShake128()
|
||||||
h.Write(seed[:])
|
_, _ = h.Write(seed[:])
|
||||||
h.Read(buf[:])
|
_, _ = h.Read(buf[:])
|
||||||
|
|
||||||
for ctr, pos := 0, 0; ctr < paramN; {
|
for ctr, pos := 0, 0; ctr < paramN; {
|
||||||
val := binary.LittleEndian.Uint16(buf[pos:])
|
val := binary.LittleEndian.Uint16(buf[pos:])
|
||||||
|
@ -128,7 +128,7 @@ func (p *poly) uniform(seed *[SeedBytes]byte, torSampling bool) {
|
||||||
pos += 2
|
pos += 2
|
||||||
if pos > shake128Rate*nBlocks-2 {
|
if pos > shake128Rate*nBlocks-2 {
|
||||||
nBlocks = 1
|
nBlocks = 1
|
||||||
h.Read(buf[:shake128Rate])
|
_, _ = h.Read(buf[:shake128Rate])
|
||||||
pos = 0
|
pos = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,10 +140,10 @@ func (p *poly) uniform(seed *[SeedBytes]byte, torSampling bool) {
|
||||||
|
|
||||||
// h and buf are left unscrubbed because the output is public.
|
// h and buf are left unscrubbed because the output is public.
|
||||||
h := sha3.NewShake128()
|
h := sha3.NewShake128()
|
||||||
h.Write(seed[:])
|
_, _ = h.Write(seed[:])
|
||||||
|
|
||||||
for {
|
for {
|
||||||
h.Read(buf[:])
|
_, _ = h.Read(buf[:])
|
||||||
if !p.discardTo(buf[:]) {
|
if !p.discardTo(buf[:]) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -159,7 +159,7 @@ func (p *poly) getNoise(seed *[SeedBytes]byte, nonce byte) {
|
||||||
var n [8]byte
|
var n [8]byte
|
||||||
|
|
||||||
n[0] = nonce
|
n[0] = nonce
|
||||||
stream, err := chacha20.NewCipher(seed[:], n[:])
|
stream, err := chacha20.New(seed[:], n[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
|
@ -1,95 +0,0 @@
|
||||||
// chacha20_amd64.go - AMD64 optimized chacha20.
|
|
||||||
//
|
|
||||||
// To the extent possible under law, Yawning Angel has waived all copyright
|
|
||||||
// and related or neighboring rights to chacha20, using the Creative
|
|
||||||
// Commons "CC0" public domain dedication. See LICENSE or
|
|
||||||
// <http://creativecommons.org/publicdomain/zero/1.0/> for full details.
|
|
||||||
|
|
||||||
// +build amd64,!gccgo,!appengine
|
|
||||||
|
|
||||||
package chacha20
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math"
|
|
||||||
)
|
|
||||||
|
|
||||||
var usingAVX2 = false
|
|
||||||
|
|
||||||
func blocksAmd64SSE2(x *uint32, inp, outp *byte, nrBlocks uint)
|
|
||||||
|
|
||||||
func blocksAmd64AVX2(x *uint32, inp, outp *byte, nrBlocks uint)
|
|
||||||
|
|
||||||
func cpuidAmd64(cpuidParams *uint32)
|
|
||||||
|
|
||||||
func xgetbv0Amd64(xcrVec *uint32)
|
|
||||||
|
|
||||||
func blocksAmd64(x *[stateSize]uint32, in []byte, out []byte, nrBlocks int, isIetf bool) {
|
|
||||||
// Probably unneeded, but stating this explicitly simplifies the assembly.
|
|
||||||
if nrBlocks == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if isIetf {
|
|
||||||
var totalBlocks uint64
|
|
||||||
totalBlocks = uint64(x[12]) + uint64(nrBlocks)
|
|
||||||
if totalBlocks > math.MaxUint32 {
|
|
||||||
panic("chacha20: Exceeded keystream per nonce limit")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if in == nil {
|
|
||||||
for i := range out {
|
|
||||||
out[i] = 0
|
|
||||||
}
|
|
||||||
in = out
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pointless to call the AVX2 code for just a single block, since half of
|
|
||||||
// the output gets discarded...
|
|
||||||
if usingAVX2 && nrBlocks > 1 {
|
|
||||||
blocksAmd64AVX2(&x[0], &in[0], &out[0], uint(nrBlocks))
|
|
||||||
} else {
|
|
||||||
blocksAmd64SSE2(&x[0], &in[0], &out[0], uint(nrBlocks))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func supportsAVX2() bool {
|
|
||||||
// https://software.intel.com/en-us/articles/how-to-detect-new-instruction-support-in-the-4th-generation-intel-core-processor-family
|
|
||||||
const (
|
|
||||||
osXsaveBit = 1 << 27
|
|
||||||
avx2Bit = 1 << 5
|
|
||||||
)
|
|
||||||
|
|
||||||
// Check to see if CPUID actually supports the leaf that indicates AVX2.
|
|
||||||
// CPUID.(EAX=0H, ECX=0H) >= 7
|
|
||||||
regs := [4]uint32{0x00}
|
|
||||||
cpuidAmd64(®s[0])
|
|
||||||
if regs[0] < 7 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check to see if the OS knows how to save/restore XMM/YMM state.
|
|
||||||
// CPUID.(EAX=01H, ECX=0H):ECX.OSXSAVE[bit 27]==1
|
|
||||||
regs = [4]uint32{0x01}
|
|
||||||
cpuidAmd64(®s[0])
|
|
||||||
if regs[2]&osXsaveBit == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
xcrRegs := [2]uint32{}
|
|
||||||
xgetbv0Amd64(&xcrRegs[0])
|
|
||||||
if xcrRegs[0]&6 != 6 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for AVX2 support.
|
|
||||||
// CPUID.(EAX=07H, ECX=0H):EBX.AVX2[bit 5]==1
|
|
||||||
regs = [4]uint32{0x07}
|
|
||||||
cpuidAmd64(®s[0])
|
|
||||||
return regs[1]&avx2Bit != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
blocksFn = blocksAmd64
|
|
||||||
usingVectors = true
|
|
||||||
usingAVX2 = supportsAVX2()
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,394 +0,0 @@
|
||||||
// chacha20_ref.go - Reference ChaCha20.
|
|
||||||
//
|
|
||||||
// To the extent possible under law, Yawning Angel has waived all copyright
|
|
||||||
// and related or neighboring rights to chacha20, using the Creative
|
|
||||||
// Commons "CC0" public domain dedication. See LICENSE or
|
|
||||||
// <http://creativecommons.org/publicdomain/zero/1.0/> for full details.
|
|
||||||
|
|
||||||
// +build !go1.9
|
|
||||||
|
|
||||||
package chacha20
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"math"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
func blocksRef(x *[stateSize]uint32, in []byte, out []byte, nrBlocks int, isIetf bool) {
|
|
||||||
if isIetf {
|
|
||||||
var totalBlocks uint64
|
|
||||||
totalBlocks = uint64(x[12]) + uint64(nrBlocks)
|
|
||||||
if totalBlocks > math.MaxUint32 {
|
|
||||||
panic("chacha20: Exceeded keystream per nonce limit")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This routine ignores x[0]...x[4] in favor the const values since it's
|
|
||||||
// ever so slightly faster.
|
|
||||||
|
|
||||||
for n := 0; n < nrBlocks; n++ {
|
|
||||||
x0, x1, x2, x3 := sigma0, sigma1, sigma2, sigma3
|
|
||||||
x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 := x[4], x[5], x[6], x[7], x[8], x[9], x[10], x[11], x[12], x[13], x[14], x[15]
|
|
||||||
|
|
||||||
for i := chachaRounds; i > 0; i -= 2 {
|
|
||||||
// quarterround(x, 0, 4, 8, 12)
|
|
||||||
x0 += x4
|
|
||||||
x12 ^= x0
|
|
||||||
x12 = (x12 << 16) | (x12 >> 16)
|
|
||||||
x8 += x12
|
|
||||||
x4 ^= x8
|
|
||||||
x4 = (x4 << 12) | (x4 >> 20)
|
|
||||||
x0 += x4
|
|
||||||
x12 ^= x0
|
|
||||||
x12 = (x12 << 8) | (x12 >> 24)
|
|
||||||
x8 += x12
|
|
||||||
x4 ^= x8
|
|
||||||
x4 = (x4 << 7) | (x4 >> 25)
|
|
||||||
|
|
||||||
// quarterround(x, 1, 5, 9, 13)
|
|
||||||
x1 += x5
|
|
||||||
x13 ^= x1
|
|
||||||
x13 = (x13 << 16) | (x13 >> 16)
|
|
||||||
x9 += x13
|
|
||||||
x5 ^= x9
|
|
||||||
x5 = (x5 << 12) | (x5 >> 20)
|
|
||||||
x1 += x5
|
|
||||||
x13 ^= x1
|
|
||||||
x13 = (x13 << 8) | (x13 >> 24)
|
|
||||||
x9 += x13
|
|
||||||
x5 ^= x9
|
|
||||||
x5 = (x5 << 7) | (x5 >> 25)
|
|
||||||
|
|
||||||
// quarterround(x, 2, 6, 10, 14)
|
|
||||||
x2 += x6
|
|
||||||
x14 ^= x2
|
|
||||||
x14 = (x14 << 16) | (x14 >> 16)
|
|
||||||
x10 += x14
|
|
||||||
x6 ^= x10
|
|
||||||
x6 = (x6 << 12) | (x6 >> 20)
|
|
||||||
x2 += x6
|
|
||||||
x14 ^= x2
|
|
||||||
x14 = (x14 << 8) | (x14 >> 24)
|
|
||||||
x10 += x14
|
|
||||||
x6 ^= x10
|
|
||||||
x6 = (x6 << 7) | (x6 >> 25)
|
|
||||||
|
|
||||||
// quarterround(x, 3, 7, 11, 15)
|
|
||||||
x3 += x7
|
|
||||||
x15 ^= x3
|
|
||||||
x15 = (x15 << 16) | (x15 >> 16)
|
|
||||||
x11 += x15
|
|
||||||
x7 ^= x11
|
|
||||||
x7 = (x7 << 12) | (x7 >> 20)
|
|
||||||
x3 += x7
|
|
||||||
x15 ^= x3
|
|
||||||
x15 = (x15 << 8) | (x15 >> 24)
|
|
||||||
x11 += x15
|
|
||||||
x7 ^= x11
|
|
||||||
x7 = (x7 << 7) | (x7 >> 25)
|
|
||||||
|
|
||||||
// quarterround(x, 0, 5, 10, 15)
|
|
||||||
x0 += x5
|
|
||||||
x15 ^= x0
|
|
||||||
x15 = (x15 << 16) | (x15 >> 16)
|
|
||||||
x10 += x15
|
|
||||||
x5 ^= x10
|
|
||||||
x5 = (x5 << 12) | (x5 >> 20)
|
|
||||||
x0 += x5
|
|
||||||
x15 ^= x0
|
|
||||||
x15 = (x15 << 8) | (x15 >> 24)
|
|
||||||
x10 += x15
|
|
||||||
x5 ^= x10
|
|
||||||
x5 = (x5 << 7) | (x5 >> 25)
|
|
||||||
|
|
||||||
// quarterround(x, 1, 6, 11, 12)
|
|
||||||
x1 += x6
|
|
||||||
x12 ^= x1
|
|
||||||
x12 = (x12 << 16) | (x12 >> 16)
|
|
||||||
x11 += x12
|
|
||||||
x6 ^= x11
|
|
||||||
x6 = (x6 << 12) | (x6 >> 20)
|
|
||||||
x1 += x6
|
|
||||||
x12 ^= x1
|
|
||||||
x12 = (x12 << 8) | (x12 >> 24)
|
|
||||||
x11 += x12
|
|
||||||
x6 ^= x11
|
|
||||||
x6 = (x6 << 7) | (x6 >> 25)
|
|
||||||
|
|
||||||
// quarterround(x, 2, 7, 8, 13)
|
|
||||||
x2 += x7
|
|
||||||
x13 ^= x2
|
|
||||||
x13 = (x13 << 16) | (x13 >> 16)
|
|
||||||
x8 += x13
|
|
||||||
x7 ^= x8
|
|
||||||
x7 = (x7 << 12) | (x7 >> 20)
|
|
||||||
x2 += x7
|
|
||||||
x13 ^= x2
|
|
||||||
x13 = (x13 << 8) | (x13 >> 24)
|
|
||||||
x8 += x13
|
|
||||||
x7 ^= x8
|
|
||||||
x7 = (x7 << 7) | (x7 >> 25)
|
|
||||||
|
|
||||||
// quarterround(x, 3, 4, 9, 14)
|
|
||||||
x3 += x4
|
|
||||||
x14 ^= x3
|
|
||||||
x14 = (x14 << 16) | (x14 >> 16)
|
|
||||||
x9 += x14
|
|
||||||
x4 ^= x9
|
|
||||||
x4 = (x4 << 12) | (x4 >> 20)
|
|
||||||
x3 += x4
|
|
||||||
x14 ^= x3
|
|
||||||
x14 = (x14 << 8) | (x14 >> 24)
|
|
||||||
x9 += x14
|
|
||||||
x4 ^= x9
|
|
||||||
x4 = (x4 << 7) | (x4 >> 25)
|
|
||||||
}
|
|
||||||
|
|
||||||
// On amd64 at least, this is a rather big boost.
|
|
||||||
if useUnsafe {
|
|
||||||
if in != nil {
|
|
||||||
inArr := (*[16]uint32)(unsafe.Pointer(&in[n*BlockSize]))
|
|
||||||
outArr := (*[16]uint32)(unsafe.Pointer(&out[n*BlockSize]))
|
|
||||||
outArr[0] = inArr[0] ^ (x0 + sigma0)
|
|
||||||
outArr[1] = inArr[1] ^ (x1 + sigma1)
|
|
||||||
outArr[2] = inArr[2] ^ (x2 + sigma2)
|
|
||||||
outArr[3] = inArr[3] ^ (x3 + sigma3)
|
|
||||||
outArr[4] = inArr[4] ^ (x4 + x[4])
|
|
||||||
outArr[5] = inArr[5] ^ (x5 + x[5])
|
|
||||||
outArr[6] = inArr[6] ^ (x6 + x[6])
|
|
||||||
outArr[7] = inArr[7] ^ (x7 + x[7])
|
|
||||||
outArr[8] = inArr[8] ^ (x8 + x[8])
|
|
||||||
outArr[9] = inArr[9] ^ (x9 + x[9])
|
|
||||||
outArr[10] = inArr[10] ^ (x10 + x[10])
|
|
||||||
outArr[11] = inArr[11] ^ (x11 + x[11])
|
|
||||||
outArr[12] = inArr[12] ^ (x12 + x[12])
|
|
||||||
outArr[13] = inArr[13] ^ (x13 + x[13])
|
|
||||||
outArr[14] = inArr[14] ^ (x14 + x[14])
|
|
||||||
outArr[15] = inArr[15] ^ (x15 + x[15])
|
|
||||||
} else {
|
|
||||||
outArr := (*[16]uint32)(unsafe.Pointer(&out[n*BlockSize]))
|
|
||||||
outArr[0] = x0 + sigma0
|
|
||||||
outArr[1] = x1 + sigma1
|
|
||||||
outArr[2] = x2 + sigma2
|
|
||||||
outArr[3] = x3 + sigma3
|
|
||||||
outArr[4] = x4 + x[4]
|
|
||||||
outArr[5] = x5 + x[5]
|
|
||||||
outArr[6] = x6 + x[6]
|
|
||||||
outArr[7] = x7 + x[7]
|
|
||||||
outArr[8] = x8 + x[8]
|
|
||||||
outArr[9] = x9 + x[9]
|
|
||||||
outArr[10] = x10 + x[10]
|
|
||||||
outArr[11] = x11 + x[11]
|
|
||||||
outArr[12] = x12 + x[12]
|
|
||||||
outArr[13] = x13 + x[13]
|
|
||||||
outArr[14] = x14 + x[14]
|
|
||||||
outArr[15] = x15 + x[15]
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Slow path, either the architecture cares about alignment, or is not little endian.
|
|
||||||
x0 += sigma0
|
|
||||||
x1 += sigma1
|
|
||||||
x2 += sigma2
|
|
||||||
x3 += sigma3
|
|
||||||
x4 += x[4]
|
|
||||||
x5 += x[5]
|
|
||||||
x6 += x[6]
|
|
||||||
x7 += x[7]
|
|
||||||
x8 += x[8]
|
|
||||||
x9 += x[9]
|
|
||||||
x10 += x[10]
|
|
||||||
x11 += x[11]
|
|
||||||
x12 += x[12]
|
|
||||||
x13 += x[13]
|
|
||||||
x14 += x[14]
|
|
||||||
x15 += x[15]
|
|
||||||
if in != nil {
|
|
||||||
binary.LittleEndian.PutUint32(out[0:4], binary.LittleEndian.Uint32(in[0:4])^x0)
|
|
||||||
binary.LittleEndian.PutUint32(out[4:8], binary.LittleEndian.Uint32(in[4:8])^x1)
|
|
||||||
binary.LittleEndian.PutUint32(out[8:12], binary.LittleEndian.Uint32(in[8:12])^x2)
|
|
||||||
binary.LittleEndian.PutUint32(out[12:16], binary.LittleEndian.Uint32(in[12:16])^x3)
|
|
||||||
binary.LittleEndian.PutUint32(out[16:20], binary.LittleEndian.Uint32(in[16:20])^x4)
|
|
||||||
binary.LittleEndian.PutUint32(out[20:24], binary.LittleEndian.Uint32(in[20:24])^x5)
|
|
||||||
binary.LittleEndian.PutUint32(out[24:28], binary.LittleEndian.Uint32(in[24:28])^x6)
|
|
||||||
binary.LittleEndian.PutUint32(out[28:32], binary.LittleEndian.Uint32(in[28:32])^x7)
|
|
||||||
binary.LittleEndian.PutUint32(out[32:36], binary.LittleEndian.Uint32(in[32:36])^x8)
|
|
||||||
binary.LittleEndian.PutUint32(out[36:40], binary.LittleEndian.Uint32(in[36:40])^x9)
|
|
||||||
binary.LittleEndian.PutUint32(out[40:44], binary.LittleEndian.Uint32(in[40:44])^x10)
|
|
||||||
binary.LittleEndian.PutUint32(out[44:48], binary.LittleEndian.Uint32(in[44:48])^x11)
|
|
||||||
binary.LittleEndian.PutUint32(out[48:52], binary.LittleEndian.Uint32(in[48:52])^x12)
|
|
||||||
binary.LittleEndian.PutUint32(out[52:56], binary.LittleEndian.Uint32(in[52:56])^x13)
|
|
||||||
binary.LittleEndian.PutUint32(out[56:60], binary.LittleEndian.Uint32(in[56:60])^x14)
|
|
||||||
binary.LittleEndian.PutUint32(out[60:64], binary.LittleEndian.Uint32(in[60:64])^x15)
|
|
||||||
in = in[BlockSize:]
|
|
||||||
} else {
|
|
||||||
binary.LittleEndian.PutUint32(out[0:4], x0)
|
|
||||||
binary.LittleEndian.PutUint32(out[4:8], x1)
|
|
||||||
binary.LittleEndian.PutUint32(out[8:12], x2)
|
|
||||||
binary.LittleEndian.PutUint32(out[12:16], x3)
|
|
||||||
binary.LittleEndian.PutUint32(out[16:20], x4)
|
|
||||||
binary.LittleEndian.PutUint32(out[20:24], x5)
|
|
||||||
binary.LittleEndian.PutUint32(out[24:28], x6)
|
|
||||||
binary.LittleEndian.PutUint32(out[28:32], x7)
|
|
||||||
binary.LittleEndian.PutUint32(out[32:36], x8)
|
|
||||||
binary.LittleEndian.PutUint32(out[36:40], x9)
|
|
||||||
binary.LittleEndian.PutUint32(out[40:44], x10)
|
|
||||||
binary.LittleEndian.PutUint32(out[44:48], x11)
|
|
||||||
binary.LittleEndian.PutUint32(out[48:52], x12)
|
|
||||||
binary.LittleEndian.PutUint32(out[52:56], x13)
|
|
||||||
binary.LittleEndian.PutUint32(out[56:60], x14)
|
|
||||||
binary.LittleEndian.PutUint32(out[60:64], x15)
|
|
||||||
}
|
|
||||||
out = out[BlockSize:]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stoping at 2^70 bytes per nonce is the user's responsibility.
|
|
||||||
ctr := uint64(x[13])<<32 | uint64(x[12])
|
|
||||||
ctr++
|
|
||||||
x[12] = uint32(ctr)
|
|
||||||
x[13] = uint32(ctr >> 32)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func hChaChaRef(x *[stateSize]uint32, out *[32]byte) {
|
|
||||||
x0, x1, x2, x3 := sigma0, sigma1, sigma2, sigma3
|
|
||||||
x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 := x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9], x[10], x[11]
|
|
||||||
|
|
||||||
for i := chachaRounds; i > 0; i -= 2 {
|
|
||||||
// quarterround(x, 0, 4, 8, 12)
|
|
||||||
x0 += x4
|
|
||||||
x12 ^= x0
|
|
||||||
x12 = (x12 << 16) | (x12 >> 16)
|
|
||||||
x8 += x12
|
|
||||||
x4 ^= x8
|
|
||||||
x4 = (x4 << 12) | (x4 >> 20)
|
|
||||||
x0 += x4
|
|
||||||
x12 ^= x0
|
|
||||||
x12 = (x12 << 8) | (x12 >> 24)
|
|
||||||
x8 += x12
|
|
||||||
x4 ^= x8
|
|
||||||
x4 = (x4 << 7) | (x4 >> 25)
|
|
||||||
|
|
||||||
// quarterround(x, 1, 5, 9, 13)
|
|
||||||
x1 += x5
|
|
||||||
x13 ^= x1
|
|
||||||
x13 = (x13 << 16) | (x13 >> 16)
|
|
||||||
x9 += x13
|
|
||||||
x5 ^= x9
|
|
||||||
x5 = (x5 << 12) | (x5 >> 20)
|
|
||||||
x1 += x5
|
|
||||||
x13 ^= x1
|
|
||||||
x13 = (x13 << 8) | (x13 >> 24)
|
|
||||||
x9 += x13
|
|
||||||
x5 ^= x9
|
|
||||||
x5 = (x5 << 7) | (x5 >> 25)
|
|
||||||
|
|
||||||
// quarterround(x, 2, 6, 10, 14)
|
|
||||||
x2 += x6
|
|
||||||
x14 ^= x2
|
|
||||||
x14 = (x14 << 16) | (x14 >> 16)
|
|
||||||
x10 += x14
|
|
||||||
x6 ^= x10
|
|
||||||
x6 = (x6 << 12) | (x6 >> 20)
|
|
||||||
x2 += x6
|
|
||||||
x14 ^= x2
|
|
||||||
x14 = (x14 << 8) | (x14 >> 24)
|
|
||||||
x10 += x14
|
|
||||||
x6 ^= x10
|
|
||||||
x6 = (x6 << 7) | (x6 >> 25)
|
|
||||||
|
|
||||||
// quarterround(x, 3, 7, 11, 15)
|
|
||||||
x3 += x7
|
|
||||||
x15 ^= x3
|
|
||||||
x15 = (x15 << 16) | (x15 >> 16)
|
|
||||||
x11 += x15
|
|
||||||
x7 ^= x11
|
|
||||||
x7 = (x7 << 12) | (x7 >> 20)
|
|
||||||
x3 += x7
|
|
||||||
x15 ^= x3
|
|
||||||
x15 = (x15 << 8) | (x15 >> 24)
|
|
||||||
x11 += x15
|
|
||||||
x7 ^= x11
|
|
||||||
x7 = (x7 << 7) | (x7 >> 25)
|
|
||||||
|
|
||||||
// quarterround(x, 0, 5, 10, 15)
|
|
||||||
x0 += x5
|
|
||||||
x15 ^= x0
|
|
||||||
x15 = (x15 << 16) | (x15 >> 16)
|
|
||||||
x10 += x15
|
|
||||||
x5 ^= x10
|
|
||||||
x5 = (x5 << 12) | (x5 >> 20)
|
|
||||||
x0 += x5
|
|
||||||
x15 ^= x0
|
|
||||||
x15 = (x15 << 8) | (x15 >> 24)
|
|
||||||
x10 += x15
|
|
||||||
x5 ^= x10
|
|
||||||
x5 = (x5 << 7) | (x5 >> 25)
|
|
||||||
|
|
||||||
// quarterround(x, 1, 6, 11, 12)
|
|
||||||
x1 += x6
|
|
||||||
x12 ^= x1
|
|
||||||
x12 = (x12 << 16) | (x12 >> 16)
|
|
||||||
x11 += x12
|
|
||||||
x6 ^= x11
|
|
||||||
x6 = (x6 << 12) | (x6 >> 20)
|
|
||||||
x1 += x6
|
|
||||||
x12 ^= x1
|
|
||||||
x12 = (x12 << 8) | (x12 >> 24)
|
|
||||||
x11 += x12
|
|
||||||
x6 ^= x11
|
|
||||||
x6 = (x6 << 7) | (x6 >> 25)
|
|
||||||
|
|
||||||
// quarterround(x, 2, 7, 8, 13)
|
|
||||||
x2 += x7
|
|
||||||
x13 ^= x2
|
|
||||||
x13 = (x13 << 16) | (x13 >> 16)
|
|
||||||
x8 += x13
|
|
||||||
x7 ^= x8
|
|
||||||
x7 = (x7 << 12) | (x7 >> 20)
|
|
||||||
x2 += x7
|
|
||||||
x13 ^= x2
|
|
||||||
x13 = (x13 << 8) | (x13 >> 24)
|
|
||||||
x8 += x13
|
|
||||||
x7 ^= x8
|
|
||||||
x7 = (x7 << 7) | (x7 >> 25)
|
|
||||||
|
|
||||||
// quarterround(x, 3, 4, 9, 14)
|
|
||||||
x3 += x4
|
|
||||||
x14 ^= x3
|
|
||||||
x14 = (x14 << 16) | (x14 >> 16)
|
|
||||||
x9 += x14
|
|
||||||
x4 ^= x9
|
|
||||||
x4 = (x4 << 12) | (x4 >> 20)
|
|
||||||
x3 += x4
|
|
||||||
x14 ^= x3
|
|
||||||
x14 = (x14 << 8) | (x14 >> 24)
|
|
||||||
x9 += x14
|
|
||||||
x4 ^= x9
|
|
||||||
x4 = (x4 << 7) | (x4 >> 25)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HChaCha returns x0...x3 | x12...x15, which corresponds to the
|
|
||||||
// indexes of the ChaCha constant and the indexes of the IV.
|
|
||||||
if useUnsafe {
|
|
||||||
outArr := (*[16]uint32)(unsafe.Pointer(&out[0]))
|
|
||||||
outArr[0] = x0
|
|
||||||
outArr[1] = x1
|
|
||||||
outArr[2] = x2
|
|
||||||
outArr[3] = x3
|
|
||||||
outArr[4] = x12
|
|
||||||
outArr[5] = x13
|
|
||||||
outArr[6] = x14
|
|
||||||
outArr[7] = x15
|
|
||||||
} else {
|
|
||||||
binary.LittleEndian.PutUint32(out[0:4], x0)
|
|
||||||
binary.LittleEndian.PutUint32(out[4:8], x1)
|
|
||||||
binary.LittleEndian.PutUint32(out[8:12], x2)
|
|
||||||
binary.LittleEndian.PutUint32(out[12:16], x3)
|
|
||||||
binary.LittleEndian.PutUint32(out[16:20], x12)
|
|
||||||
binary.LittleEndian.PutUint32(out[20:24], x13)
|
|
||||||
binary.LittleEndian.PutUint32(out[24:28], x14)
|
|
||||||
binary.LittleEndian.PutUint32(out[28:32], x15)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
|
@ -1,395 +0,0 @@
|
||||||
// chacha20_ref.go - Reference ChaCha20.
|
|
||||||
//
|
|
||||||
// To the extent possible under law, Yawning Angel has waived all copyright
|
|
||||||
// and related or neighboring rights to chacha20, using the Creative
|
|
||||||
// Commons "CC0" public domain dedication. See LICENSE or
|
|
||||||
// <http://creativecommons.org/publicdomain/zero/1.0/> for full details.
|
|
||||||
|
|
||||||
// +build go1.9
|
|
||||||
|
|
||||||
package chacha20
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"math"
|
|
||||||
"math/bits"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
func blocksRef(x *[stateSize]uint32, in []byte, out []byte, nrBlocks int, isIetf bool) {
|
|
||||||
if isIetf {
|
|
||||||
var totalBlocks uint64
|
|
||||||
totalBlocks = uint64(x[12]) + uint64(nrBlocks)
|
|
||||||
if totalBlocks > math.MaxUint32 {
|
|
||||||
panic("chacha20: Exceeded keystream per nonce limit")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This routine ignores x[0]...x[4] in favor the const values since it's
|
|
||||||
// ever so slightly faster.
|
|
||||||
|
|
||||||
for n := 0; n < nrBlocks; n++ {
|
|
||||||
x0, x1, x2, x3 := sigma0, sigma1, sigma2, sigma3
|
|
||||||
x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 := x[4], x[5], x[6], x[7], x[8], x[9], x[10], x[11], x[12], x[13], x[14], x[15]
|
|
||||||
|
|
||||||
for i := chachaRounds; i > 0; i -= 2 {
|
|
||||||
// quarterround(x, 0, 4, 8, 12)
|
|
||||||
x0 += x4
|
|
||||||
x12 ^= x0
|
|
||||||
x12 = bits.RotateLeft32(x12, 16)
|
|
||||||
x8 += x12
|
|
||||||
x4 ^= x8
|
|
||||||
x4 = bits.RotateLeft32(x4, 12)
|
|
||||||
x0 += x4
|
|
||||||
x12 ^= x0
|
|
||||||
x12 = bits.RotateLeft32(x12, 8)
|
|
||||||
x8 += x12
|
|
||||||
x4 ^= x8
|
|
||||||
x4 = bits.RotateLeft32(x4, 7)
|
|
||||||
|
|
||||||
// quarterround(x, 1, 5, 9, 13)
|
|
||||||
x1 += x5
|
|
||||||
x13 ^= x1
|
|
||||||
x13 = bits.RotateLeft32(x13, 16)
|
|
||||||
x9 += x13
|
|
||||||
x5 ^= x9
|
|
||||||
x5 = bits.RotateLeft32(x5, 12)
|
|
||||||
x1 += x5
|
|
||||||
x13 ^= x1
|
|
||||||
x13 = bits.RotateLeft32(x13, 8)
|
|
||||||
x9 += x13
|
|
||||||
x5 ^= x9
|
|
||||||
x5 = bits.RotateLeft32(x5, 7)
|
|
||||||
|
|
||||||
// quarterround(x, 2, 6, 10, 14)
|
|
||||||
x2 += x6
|
|
||||||
x14 ^= x2
|
|
||||||
x14 = bits.RotateLeft32(x14, 16)
|
|
||||||
x10 += x14
|
|
||||||
x6 ^= x10
|
|
||||||
x6 = bits.RotateLeft32(x6, 12)
|
|
||||||
x2 += x6
|
|
||||||
x14 ^= x2
|
|
||||||
x14 = bits.RotateLeft32(x14, 8)
|
|
||||||
x10 += x14
|
|
||||||
x6 ^= x10
|
|
||||||
x6 = bits.RotateLeft32(x6, 7)
|
|
||||||
|
|
||||||
// quarterround(x, 3, 7, 11, 15)
|
|
||||||
x3 += x7
|
|
||||||
x15 ^= x3
|
|
||||||
x15 = bits.RotateLeft32(x15, 16)
|
|
||||||
x11 += x15
|
|
||||||
x7 ^= x11
|
|
||||||
x7 = bits.RotateLeft32(x7, 12)
|
|
||||||
x3 += x7
|
|
||||||
x15 ^= x3
|
|
||||||
x15 = bits.RotateLeft32(x15, 8)
|
|
||||||
x11 += x15
|
|
||||||
x7 ^= x11
|
|
||||||
x7 = bits.RotateLeft32(x7, 7)
|
|
||||||
|
|
||||||
// quarterround(x, 0, 5, 10, 15)
|
|
||||||
x0 += x5
|
|
||||||
x15 ^= x0
|
|
||||||
x15 = bits.RotateLeft32(x15, 16)
|
|
||||||
x10 += x15
|
|
||||||
x5 ^= x10
|
|
||||||
x5 = bits.RotateLeft32(x5, 12)
|
|
||||||
x0 += x5
|
|
||||||
x15 ^= x0
|
|
||||||
x15 = bits.RotateLeft32(x15, 8)
|
|
||||||
x10 += x15
|
|
||||||
x5 ^= x10
|
|
||||||
x5 = bits.RotateLeft32(x5, 7)
|
|
||||||
|
|
||||||
// quarterround(x, 1, 6, 11, 12)
|
|
||||||
x1 += x6
|
|
||||||
x12 ^= x1
|
|
||||||
x12 = bits.RotateLeft32(x12, 16)
|
|
||||||
x11 += x12
|
|
||||||
x6 ^= x11
|
|
||||||
x6 = bits.RotateLeft32(x6, 12)
|
|
||||||
x1 += x6
|
|
||||||
x12 ^= x1
|
|
||||||
x12 = bits.RotateLeft32(x12, 8)
|
|
||||||
x11 += x12
|
|
||||||
x6 ^= x11
|
|
||||||
x6 = bits.RotateLeft32(x6, 7)
|
|
||||||
|
|
||||||
// quarterround(x, 2, 7, 8, 13)
|
|
||||||
x2 += x7
|
|
||||||
x13 ^= x2
|
|
||||||
x13 = bits.RotateLeft32(x13, 16)
|
|
||||||
x8 += x13
|
|
||||||
x7 ^= x8
|
|
||||||
x7 = bits.RotateLeft32(x7, 12)
|
|
||||||
x2 += x7
|
|
||||||
x13 ^= x2
|
|
||||||
x13 = bits.RotateLeft32(x13, 8)
|
|
||||||
x8 += x13
|
|
||||||
x7 ^= x8
|
|
||||||
x7 = bits.RotateLeft32(x7, 7)
|
|
||||||
|
|
||||||
// quarterround(x, 3, 4, 9, 14)
|
|
||||||
x3 += x4
|
|
||||||
x14 ^= x3
|
|
||||||
x14 = bits.RotateLeft32(x14, 16)
|
|
||||||
x9 += x14
|
|
||||||
x4 ^= x9
|
|
||||||
x4 = bits.RotateLeft32(x4, 12)
|
|
||||||
x3 += x4
|
|
||||||
x14 ^= x3
|
|
||||||
x14 = bits.RotateLeft32(x14, 8)
|
|
||||||
x9 += x14
|
|
||||||
x4 ^= x9
|
|
||||||
x4 = bits.RotateLeft32(x4, 7)
|
|
||||||
}
|
|
||||||
|
|
||||||
// On amd64 at least, this is a rather big boost.
|
|
||||||
if useUnsafe {
|
|
||||||
if in != nil {
|
|
||||||
inArr := (*[16]uint32)(unsafe.Pointer(&in[n*BlockSize]))
|
|
||||||
outArr := (*[16]uint32)(unsafe.Pointer(&out[n*BlockSize]))
|
|
||||||
outArr[0] = inArr[0] ^ (x0 + sigma0)
|
|
||||||
outArr[1] = inArr[1] ^ (x1 + sigma1)
|
|
||||||
outArr[2] = inArr[2] ^ (x2 + sigma2)
|
|
||||||
outArr[3] = inArr[3] ^ (x3 + sigma3)
|
|
||||||
outArr[4] = inArr[4] ^ (x4 + x[4])
|
|
||||||
outArr[5] = inArr[5] ^ (x5 + x[5])
|
|
||||||
outArr[6] = inArr[6] ^ (x6 + x[6])
|
|
||||||
outArr[7] = inArr[7] ^ (x7 + x[7])
|
|
||||||
outArr[8] = inArr[8] ^ (x8 + x[8])
|
|
||||||
outArr[9] = inArr[9] ^ (x9 + x[9])
|
|
||||||
outArr[10] = inArr[10] ^ (x10 + x[10])
|
|
||||||
outArr[11] = inArr[11] ^ (x11 + x[11])
|
|
||||||
outArr[12] = inArr[12] ^ (x12 + x[12])
|
|
||||||
outArr[13] = inArr[13] ^ (x13 + x[13])
|
|
||||||
outArr[14] = inArr[14] ^ (x14 + x[14])
|
|
||||||
outArr[15] = inArr[15] ^ (x15 + x[15])
|
|
||||||
} else {
|
|
||||||
outArr := (*[16]uint32)(unsafe.Pointer(&out[n*BlockSize]))
|
|
||||||
outArr[0] = x0 + sigma0
|
|
||||||
outArr[1] = x1 + sigma1
|
|
||||||
outArr[2] = x2 + sigma2
|
|
||||||
outArr[3] = x3 + sigma3
|
|
||||||
outArr[4] = x4 + x[4]
|
|
||||||
outArr[5] = x5 + x[5]
|
|
||||||
outArr[6] = x6 + x[6]
|
|
||||||
outArr[7] = x7 + x[7]
|
|
||||||
outArr[8] = x8 + x[8]
|
|
||||||
outArr[9] = x9 + x[9]
|
|
||||||
outArr[10] = x10 + x[10]
|
|
||||||
outArr[11] = x11 + x[11]
|
|
||||||
outArr[12] = x12 + x[12]
|
|
||||||
outArr[13] = x13 + x[13]
|
|
||||||
outArr[14] = x14 + x[14]
|
|
||||||
outArr[15] = x15 + x[15]
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Slow path, either the architecture cares about alignment, or is not little endian.
|
|
||||||
x0 += sigma0
|
|
||||||
x1 += sigma1
|
|
||||||
x2 += sigma2
|
|
||||||
x3 += sigma3
|
|
||||||
x4 += x[4]
|
|
||||||
x5 += x[5]
|
|
||||||
x6 += x[6]
|
|
||||||
x7 += x[7]
|
|
||||||
x8 += x[8]
|
|
||||||
x9 += x[9]
|
|
||||||
x10 += x[10]
|
|
||||||
x11 += x[11]
|
|
||||||
x12 += x[12]
|
|
||||||
x13 += x[13]
|
|
||||||
x14 += x[14]
|
|
||||||
x15 += x[15]
|
|
||||||
if in != nil {
|
|
||||||
binary.LittleEndian.PutUint32(out[0:4], binary.LittleEndian.Uint32(in[0:4])^x0)
|
|
||||||
binary.LittleEndian.PutUint32(out[4:8], binary.LittleEndian.Uint32(in[4:8])^x1)
|
|
||||||
binary.LittleEndian.PutUint32(out[8:12], binary.LittleEndian.Uint32(in[8:12])^x2)
|
|
||||||
binary.LittleEndian.PutUint32(out[12:16], binary.LittleEndian.Uint32(in[12:16])^x3)
|
|
||||||
binary.LittleEndian.PutUint32(out[16:20], binary.LittleEndian.Uint32(in[16:20])^x4)
|
|
||||||
binary.LittleEndian.PutUint32(out[20:24], binary.LittleEndian.Uint32(in[20:24])^x5)
|
|
||||||
binary.LittleEndian.PutUint32(out[24:28], binary.LittleEndian.Uint32(in[24:28])^x6)
|
|
||||||
binary.LittleEndian.PutUint32(out[28:32], binary.LittleEndian.Uint32(in[28:32])^x7)
|
|
||||||
binary.LittleEndian.PutUint32(out[32:36], binary.LittleEndian.Uint32(in[32:36])^x8)
|
|
||||||
binary.LittleEndian.PutUint32(out[36:40], binary.LittleEndian.Uint32(in[36:40])^x9)
|
|
||||||
binary.LittleEndian.PutUint32(out[40:44], binary.LittleEndian.Uint32(in[40:44])^x10)
|
|
||||||
binary.LittleEndian.PutUint32(out[44:48], binary.LittleEndian.Uint32(in[44:48])^x11)
|
|
||||||
binary.LittleEndian.PutUint32(out[48:52], binary.LittleEndian.Uint32(in[48:52])^x12)
|
|
||||||
binary.LittleEndian.PutUint32(out[52:56], binary.LittleEndian.Uint32(in[52:56])^x13)
|
|
||||||
binary.LittleEndian.PutUint32(out[56:60], binary.LittleEndian.Uint32(in[56:60])^x14)
|
|
||||||
binary.LittleEndian.PutUint32(out[60:64], binary.LittleEndian.Uint32(in[60:64])^x15)
|
|
||||||
in = in[BlockSize:]
|
|
||||||
} else {
|
|
||||||
binary.LittleEndian.PutUint32(out[0:4], x0)
|
|
||||||
binary.LittleEndian.PutUint32(out[4:8], x1)
|
|
||||||
binary.LittleEndian.PutUint32(out[8:12], x2)
|
|
||||||
binary.LittleEndian.PutUint32(out[12:16], x3)
|
|
||||||
binary.LittleEndian.PutUint32(out[16:20], x4)
|
|
||||||
binary.LittleEndian.PutUint32(out[20:24], x5)
|
|
||||||
binary.LittleEndian.PutUint32(out[24:28], x6)
|
|
||||||
binary.LittleEndian.PutUint32(out[28:32], x7)
|
|
||||||
binary.LittleEndian.PutUint32(out[32:36], x8)
|
|
||||||
binary.LittleEndian.PutUint32(out[36:40], x9)
|
|
||||||
binary.LittleEndian.PutUint32(out[40:44], x10)
|
|
||||||
binary.LittleEndian.PutUint32(out[44:48], x11)
|
|
||||||
binary.LittleEndian.PutUint32(out[48:52], x12)
|
|
||||||
binary.LittleEndian.PutUint32(out[52:56], x13)
|
|
||||||
binary.LittleEndian.PutUint32(out[56:60], x14)
|
|
||||||
binary.LittleEndian.PutUint32(out[60:64], x15)
|
|
||||||
}
|
|
||||||
out = out[BlockSize:]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stoping at 2^70 bytes per nonce is the user's responsibility.
|
|
||||||
ctr := uint64(x[13])<<32 | uint64(x[12])
|
|
||||||
ctr++
|
|
||||||
x[12] = uint32(ctr)
|
|
||||||
x[13] = uint32(ctr >> 32)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func hChaChaRef(x *[stateSize]uint32, out *[32]byte) {
|
|
||||||
x0, x1, x2, x3 := sigma0, sigma1, sigma2, sigma3
|
|
||||||
x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 := x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9], x[10], x[11]
|
|
||||||
|
|
||||||
for i := chachaRounds; i > 0; i -= 2 {
|
|
||||||
// quarterround(x, 0, 4, 8, 12)
|
|
||||||
x0 += x4
|
|
||||||
x12 ^= x0
|
|
||||||
x12 = bits.RotateLeft32(x12, 16)
|
|
||||||
x8 += x12
|
|
||||||
x4 ^= x8
|
|
||||||
x4 = bits.RotateLeft32(x4, 12)
|
|
||||||
x0 += x4
|
|
||||||
x12 ^= x0
|
|
||||||
x12 = bits.RotateLeft32(x12, 8)
|
|
||||||
x8 += x12
|
|
||||||
x4 ^= x8
|
|
||||||
x4 = bits.RotateLeft32(x4, 7)
|
|
||||||
|
|
||||||
// quarterround(x, 1, 5, 9, 13)
|
|
||||||
x1 += x5
|
|
||||||
x13 ^= x1
|
|
||||||
x13 = bits.RotateLeft32(x13, 16)
|
|
||||||
x9 += x13
|
|
||||||
x5 ^= x9
|
|
||||||
x5 = bits.RotateLeft32(x5, 12)
|
|
||||||
x1 += x5
|
|
||||||
x13 ^= x1
|
|
||||||
x13 = bits.RotateLeft32(x13, 8)
|
|
||||||
x9 += x13
|
|
||||||
x5 ^= x9
|
|
||||||
x5 = bits.RotateLeft32(x5, 7)
|
|
||||||
|
|
||||||
// quarterround(x, 2, 6, 10, 14)
|
|
||||||
x2 += x6
|
|
||||||
x14 ^= x2
|
|
||||||
x14 = bits.RotateLeft32(x14, 16)
|
|
||||||
x10 += x14
|
|
||||||
x6 ^= x10
|
|
||||||
x6 = bits.RotateLeft32(x6, 12)
|
|
||||||
x2 += x6
|
|
||||||
x14 ^= x2
|
|
||||||
x14 = bits.RotateLeft32(x14, 8)
|
|
||||||
x10 += x14
|
|
||||||
x6 ^= x10
|
|
||||||
x6 = bits.RotateLeft32(x6, 7)
|
|
||||||
|
|
||||||
// quarterround(x, 3, 7, 11, 15)
|
|
||||||
x3 += x7
|
|
||||||
x15 ^= x3
|
|
||||||
x15 = bits.RotateLeft32(x15, 16)
|
|
||||||
x11 += x15
|
|
||||||
x7 ^= x11
|
|
||||||
x7 = bits.RotateLeft32(x7, 12)
|
|
||||||
x3 += x7
|
|
||||||
x15 ^= x3
|
|
||||||
x15 = bits.RotateLeft32(x15, 8)
|
|
||||||
x11 += x15
|
|
||||||
x7 ^= x11
|
|
||||||
x7 = bits.RotateLeft32(x7, 7)
|
|
||||||
|
|
||||||
// quarterround(x, 0, 5, 10, 15)
|
|
||||||
x0 += x5
|
|
||||||
x15 ^= x0
|
|
||||||
x15 = bits.RotateLeft32(x15, 16)
|
|
||||||
x10 += x15
|
|
||||||
x5 ^= x10
|
|
||||||
x5 = bits.RotateLeft32(x5, 12)
|
|
||||||
x0 += x5
|
|
||||||
x15 ^= x0
|
|
||||||
x15 = bits.RotateLeft32(x15, 8)
|
|
||||||
x10 += x15
|
|
||||||
x5 ^= x10
|
|
||||||
x5 = bits.RotateLeft32(x5, 7)
|
|
||||||
|
|
||||||
// quarterround(x, 1, 6, 11, 12)
|
|
||||||
x1 += x6
|
|
||||||
x12 ^= x1
|
|
||||||
x12 = bits.RotateLeft32(x12, 16)
|
|
||||||
x11 += x12
|
|
||||||
x6 ^= x11
|
|
||||||
x6 = bits.RotateLeft32(x6, 12)
|
|
||||||
x1 += x6
|
|
||||||
x12 ^= x1
|
|
||||||
x12 = bits.RotateLeft32(x12, 8)
|
|
||||||
x11 += x12
|
|
||||||
x6 ^= x11
|
|
||||||
x6 = bits.RotateLeft32(x6, 7)
|
|
||||||
|
|
||||||
// quarterround(x, 2, 7, 8, 13)
|
|
||||||
x2 += x7
|
|
||||||
x13 ^= x2
|
|
||||||
x13 = bits.RotateLeft32(x13, 16)
|
|
||||||
x8 += x13
|
|
||||||
x7 ^= x8
|
|
||||||
x7 = bits.RotateLeft32(x7, 12)
|
|
||||||
x2 += x7
|
|
||||||
x13 ^= x2
|
|
||||||
x13 = bits.RotateLeft32(x13, 8)
|
|
||||||
x8 += x13
|
|
||||||
x7 ^= x8
|
|
||||||
x7 = bits.RotateLeft32(x7, 7)
|
|
||||||
|
|
||||||
// quarterround(x, 3, 4, 9, 14)
|
|
||||||
x3 += x4
|
|
||||||
x14 ^= x3
|
|
||||||
x14 = bits.RotateLeft32(x14, 16)
|
|
||||||
x9 += x14
|
|
||||||
x4 ^= x9
|
|
||||||
x4 = bits.RotateLeft32(x4, 12)
|
|
||||||
x3 += x4
|
|
||||||
x14 ^= x3
|
|
||||||
x14 = bits.RotateLeft32(x14, 8)
|
|
||||||
x9 += x14
|
|
||||||
x4 ^= x9
|
|
||||||
x4 = bits.RotateLeft32(x4, 7)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HChaCha returns x0...x3 | x12...x15, which corresponds to the
|
|
||||||
// indexes of the ChaCha constant and the indexes of the IV.
|
|
||||||
if useUnsafe {
|
|
||||||
outArr := (*[16]uint32)(unsafe.Pointer(&out[0]))
|
|
||||||
outArr[0] = x0
|
|
||||||
outArr[1] = x1
|
|
||||||
outArr[2] = x2
|
|
||||||
outArr[3] = x3
|
|
||||||
outArr[4] = x12
|
|
||||||
outArr[5] = x13
|
|
||||||
outArr[6] = x14
|
|
||||||
outArr[7] = x15
|
|
||||||
} else {
|
|
||||||
binary.LittleEndian.PutUint32(out[0:4], x0)
|
|
||||||
binary.LittleEndian.PutUint32(out[4:8], x1)
|
|
||||||
binary.LittleEndian.PutUint32(out[8:12], x2)
|
|
||||||
binary.LittleEndian.PutUint32(out[12:16], x3)
|
|
||||||
binary.LittleEndian.PutUint32(out[16:20], x12)
|
|
||||||
binary.LittleEndian.PutUint32(out[20:24], x13)
|
|
||||||
binary.LittleEndian.PutUint32(out[24:28], x14)
|
|
||||||
binary.LittleEndian.PutUint32(out[28:32], x15)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
|
@ -1,122 +0,0 @@
|
||||||
Creative Commons Legal Code
|
|
||||||
|
|
||||||
CC0 1.0 Universal
|
|
||||||
|
|
||||||
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
|
||||||
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
|
||||||
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
|
||||||
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
|
||||||
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
|
||||||
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
|
||||||
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
|
||||||
HEREUNDER.
|
|
||||||
|
|
||||||
Statement of Purpose
|
|
||||||
|
|
||||||
The laws of most jurisdictions throughout the world automatically confer
|
|
||||||
exclusive Copyright and Related Rights (defined below) upon the creator
|
|
||||||
and subsequent owner(s) (each and all, an "owner") of an original work of
|
|
||||||
authorship and/or a database (each, a "Work").
|
|
||||||
|
|
||||||
Certain owners wish to permanently relinquish those rights to a Work for
|
|
||||||
the purpose of contributing to a commons of creative, cultural and
|
|
||||||
scientific works ("Commons") that the public can reliably and without fear
|
|
||||||
of later claims of infringement build upon, modify, incorporate in other
|
|
||||||
works, reuse and redistribute as freely as possible in any form whatsoever
|
|
||||||
and for any purposes, including without limitation commercial purposes.
|
|
||||||
These owners may contribute to the Commons to promote the ideal of a free
|
|
||||||
culture and the further production of creative, cultural and scientific
|
|
||||||
works, or to gain reputation or greater distribution for their Work in
|
|
||||||
part through the use and efforts of others.
|
|
||||||
|
|
||||||
For these and/or other purposes and motivations, and without any
|
|
||||||
expectation of additional consideration or compensation, the person
|
|
||||||
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
|
|
||||||
is an owner of Copyright and Related Rights in the Work, voluntarily
|
|
||||||
elects to apply CC0 to the Work and publicly distribute the Work under its
|
|
||||||
terms, with knowledge of his or her Copyright and Related Rights in the
|
|
||||||
Work and the meaning and intended legal effect of CC0 on those rights.
|
|
||||||
|
|
||||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
|
||||||
protected by copyright and related or neighboring rights ("Copyright and
|
|
||||||
Related Rights"). Copyright and Related Rights include, but are not
|
|
||||||
limited to, the following:
|
|
||||||
|
|
||||||
i. the right to reproduce, adapt, distribute, perform, display,
|
|
||||||
communicate, and translate a Work;
|
|
||||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
|
||||||
iii. publicity and privacy rights pertaining to a person's image or
|
|
||||||
likeness depicted in a Work;
|
|
||||||
iv. rights protecting against unfair competition in regards to a Work,
|
|
||||||
subject to the limitations in paragraph 4(a), below;
|
|
||||||
v. rights protecting the extraction, dissemination, use and reuse of data
|
|
||||||
in a Work;
|
|
||||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
|
||||||
European Parliament and of the Council of 11 March 1996 on the legal
|
|
||||||
protection of databases, and under any national implementation
|
|
||||||
thereof, including any amended or successor version of such
|
|
||||||
directive); and
|
|
||||||
vii. other similar, equivalent or corresponding rights throughout the
|
|
||||||
world based on applicable law or treaty, and any national
|
|
||||||
implementations thereof.
|
|
||||||
|
|
||||||
2. Waiver. To the greatest extent permitted by, but not in contravention
|
|
||||||
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
|
||||||
irrevocably and unconditionally waives, abandons, and surrenders all of
|
|
||||||
Affirmer's Copyright and Related Rights and associated claims and causes
|
|
||||||
of action, whether now known or unknown (including existing as well as
|
|
||||||
future claims and causes of action), in the Work (i) in all territories
|
|
||||||
worldwide, (ii) for the maximum duration provided by applicable law or
|
|
||||||
treaty (including future time extensions), (iii) in any current or future
|
|
||||||
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
|
||||||
including without limitation commercial, advertising or promotional
|
|
||||||
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
|
|
||||||
member of the public at large and to the detriment of Affirmer's heirs and
|
|
||||||
successors, fully intending that such Waiver shall not be subject to
|
|
||||||
revocation, rescission, cancellation, termination, or any other legal or
|
|
||||||
equitable action to disrupt the quiet enjoyment of the Work by the public
|
|
||||||
as contemplated by Affirmer's express Statement of Purpose.
|
|
||||||
|
|
||||||
3. Public License Fallback. Should any part of the Waiver for any reason
|
|
||||||
be judged legally invalid or ineffective under applicable law, then the
|
|
||||||
Waiver shall be preserved to the maximum extent permitted taking into
|
|
||||||
account Affirmer's express Statement of Purpose. In addition, to the
|
|
||||||
extent the Waiver is so judged Affirmer hereby grants to each affected
|
|
||||||
person a royalty-free, non transferable, non sublicensable, non exclusive,
|
|
||||||
irrevocable and unconditional license to exercise Affirmer's Copyright and
|
|
||||||
Related Rights in the Work (i) in all territories worldwide, (ii) for the
|
|
||||||
maximum duration provided by applicable law or treaty (including future
|
|
||||||
time extensions), (iii) in any current or future medium and for any number
|
|
||||||
of copies, and (iv) for any purpose whatsoever, including without
|
|
||||||
limitation commercial, advertising or promotional purposes (the
|
|
||||||
"License"). The License shall be deemed effective as of the date CC0 was
|
|
||||||
applied by Affirmer to the Work. Should any part of the License for any
|
|
||||||
reason be judged legally invalid or ineffective under applicable law, such
|
|
||||||
partial invalidity or ineffectiveness shall not invalidate the remainder
|
|
||||||
of the License, and in such case Affirmer hereby affirms that he or she
|
|
||||||
will not (i) exercise any of his or her remaining Copyright and Related
|
|
||||||
Rights in the Work or (ii) assert any associated claims and causes of
|
|
||||||
action with respect to the Work, in either case contrary to Affirmer's
|
|
||||||
express Statement of Purpose.
|
|
||||||
|
|
||||||
4. Limitations and Disclaimers.
|
|
||||||
|
|
||||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
|
||||||
surrendered, licensed or otherwise affected by this document.
|
|
||||||
b. Affirmer offers the Work as-is and makes no representations or
|
|
||||||
warranties of any kind concerning the Work, express, implied,
|
|
||||||
statutory or otherwise, including without limitation warranties of
|
|
||||||
title, merchantability, fitness for a particular purpose, non
|
|
||||||
infringement, or the absence of latent or other defects, accuracy, or
|
|
||||||
the present or absence of errors, whether or not discoverable, all to
|
|
||||||
the greatest extent permissible under applicable law.
|
|
||||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
|
||||||
that may apply to the Work or any use thereof, including without
|
|
||||||
limitation any person's Copyright and Related Rights in the Work.
|
|
||||||
Further, Affirmer disclaims responsibility for obtaining any necessary
|
|
||||||
consents, permissions or other rights required for any use of the
|
|
||||||
Work.
|
|
||||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
|
||||||
party to this document and has no duty or obligation with respect to
|
|
||||||
this CC0 or use of the Work.
|
|
||||||
|
|
|
@ -4,7 +4,10 @@
|
||||||
|
|
||||||
package blake2b
|
package blake2b
|
||||||
|
|
||||||
import "encoding/binary"
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"math/bits"
|
||||||
|
)
|
||||||
|
|
||||||
// the precomputed values for BLAKE2b
|
// the precomputed values for BLAKE2b
|
||||||
// there are 12 16-byte arrays - one for each round
|
// there are 12 16-byte arrays - one for each round
|
||||||
|
@ -51,118 +54,118 @@ func hashBlocksGeneric(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) {
|
||||||
v0 += m[s[0]]
|
v0 += m[s[0]]
|
||||||
v0 += v4
|
v0 += v4
|
||||||
v12 ^= v0
|
v12 ^= v0
|
||||||
v12 = v12<<(64-32) | v12>>32
|
v12 = bits.RotateLeft64(v12, -32)
|
||||||
v8 += v12
|
v8 += v12
|
||||||
v4 ^= v8
|
v4 ^= v8
|
||||||
v4 = v4<<(64-24) | v4>>24
|
v4 = bits.RotateLeft64(v4, -24)
|
||||||
v1 += m[s[1]]
|
v1 += m[s[1]]
|
||||||
v1 += v5
|
v1 += v5
|
||||||
v13 ^= v1
|
v13 ^= v1
|
||||||
v13 = v13<<(64-32) | v13>>32
|
v13 = bits.RotateLeft64(v13, -32)
|
||||||
v9 += v13
|
v9 += v13
|
||||||
v5 ^= v9
|
v5 ^= v9
|
||||||
v5 = v5<<(64-24) | v5>>24
|
v5 = bits.RotateLeft64(v5, -24)
|
||||||
v2 += m[s[2]]
|
v2 += m[s[2]]
|
||||||
v2 += v6
|
v2 += v6
|
||||||
v14 ^= v2
|
v14 ^= v2
|
||||||
v14 = v14<<(64-32) | v14>>32
|
v14 = bits.RotateLeft64(v14, -32)
|
||||||
v10 += v14
|
v10 += v14
|
||||||
v6 ^= v10
|
v6 ^= v10
|
||||||
v6 = v6<<(64-24) | v6>>24
|
v6 = bits.RotateLeft64(v6, -24)
|
||||||
v3 += m[s[3]]
|
v3 += m[s[3]]
|
||||||
v3 += v7
|
v3 += v7
|
||||||
v15 ^= v3
|
v15 ^= v3
|
||||||
v15 = v15<<(64-32) | v15>>32
|
v15 = bits.RotateLeft64(v15, -32)
|
||||||
v11 += v15
|
v11 += v15
|
||||||
v7 ^= v11
|
v7 ^= v11
|
||||||
v7 = v7<<(64-24) | v7>>24
|
v7 = bits.RotateLeft64(v7, -24)
|
||||||
|
|
||||||
v0 += m[s[4]]
|
v0 += m[s[4]]
|
||||||
v0 += v4
|
v0 += v4
|
||||||
v12 ^= v0
|
v12 ^= v0
|
||||||
v12 = v12<<(64-16) | v12>>16
|
v12 = bits.RotateLeft64(v12, -16)
|
||||||
v8 += v12
|
v8 += v12
|
||||||
v4 ^= v8
|
v4 ^= v8
|
||||||
v4 = v4<<(64-63) | v4>>63
|
v4 = bits.RotateLeft64(v4, -63)
|
||||||
v1 += m[s[5]]
|
v1 += m[s[5]]
|
||||||
v1 += v5
|
v1 += v5
|
||||||
v13 ^= v1
|
v13 ^= v1
|
||||||
v13 = v13<<(64-16) | v13>>16
|
v13 = bits.RotateLeft64(v13, -16)
|
||||||
v9 += v13
|
v9 += v13
|
||||||
v5 ^= v9
|
v5 ^= v9
|
||||||
v5 = v5<<(64-63) | v5>>63
|
v5 = bits.RotateLeft64(v5, -63)
|
||||||
v2 += m[s[6]]
|
v2 += m[s[6]]
|
||||||
v2 += v6
|
v2 += v6
|
||||||
v14 ^= v2
|
v14 ^= v2
|
||||||
v14 = v14<<(64-16) | v14>>16
|
v14 = bits.RotateLeft64(v14, -16)
|
||||||
v10 += v14
|
v10 += v14
|
||||||
v6 ^= v10
|
v6 ^= v10
|
||||||
v6 = v6<<(64-63) | v6>>63
|
v6 = bits.RotateLeft64(v6, -63)
|
||||||
v3 += m[s[7]]
|
v3 += m[s[7]]
|
||||||
v3 += v7
|
v3 += v7
|
||||||
v15 ^= v3
|
v15 ^= v3
|
||||||
v15 = v15<<(64-16) | v15>>16
|
v15 = bits.RotateLeft64(v15, -16)
|
||||||
v11 += v15
|
v11 += v15
|
||||||
v7 ^= v11
|
v7 ^= v11
|
||||||
v7 = v7<<(64-63) | v7>>63
|
v7 = bits.RotateLeft64(v7, -63)
|
||||||
|
|
||||||
v0 += m[s[8]]
|
v0 += m[s[8]]
|
||||||
v0 += v5
|
v0 += v5
|
||||||
v15 ^= v0
|
v15 ^= v0
|
||||||
v15 = v15<<(64-32) | v15>>32
|
v15 = bits.RotateLeft64(v15, -32)
|
||||||
v10 += v15
|
v10 += v15
|
||||||
v5 ^= v10
|
v5 ^= v10
|
||||||
v5 = v5<<(64-24) | v5>>24
|
v5 = bits.RotateLeft64(v5, -24)
|
||||||
v1 += m[s[9]]
|
v1 += m[s[9]]
|
||||||
v1 += v6
|
v1 += v6
|
||||||
v12 ^= v1
|
v12 ^= v1
|
||||||
v12 = v12<<(64-32) | v12>>32
|
v12 = bits.RotateLeft64(v12, -32)
|
||||||
v11 += v12
|
v11 += v12
|
||||||
v6 ^= v11
|
v6 ^= v11
|
||||||
v6 = v6<<(64-24) | v6>>24
|
v6 = bits.RotateLeft64(v6, -24)
|
||||||
v2 += m[s[10]]
|
v2 += m[s[10]]
|
||||||
v2 += v7
|
v2 += v7
|
||||||
v13 ^= v2
|
v13 ^= v2
|
||||||
v13 = v13<<(64-32) | v13>>32
|
v13 = bits.RotateLeft64(v13, -32)
|
||||||
v8 += v13
|
v8 += v13
|
||||||
v7 ^= v8
|
v7 ^= v8
|
||||||
v7 = v7<<(64-24) | v7>>24
|
v7 = bits.RotateLeft64(v7, -24)
|
||||||
v3 += m[s[11]]
|
v3 += m[s[11]]
|
||||||
v3 += v4
|
v3 += v4
|
||||||
v14 ^= v3
|
v14 ^= v3
|
||||||
v14 = v14<<(64-32) | v14>>32
|
v14 = bits.RotateLeft64(v14, -32)
|
||||||
v9 += v14
|
v9 += v14
|
||||||
v4 ^= v9
|
v4 ^= v9
|
||||||
v4 = v4<<(64-24) | v4>>24
|
v4 = bits.RotateLeft64(v4, -24)
|
||||||
|
|
||||||
v0 += m[s[12]]
|
v0 += m[s[12]]
|
||||||
v0 += v5
|
v0 += v5
|
||||||
v15 ^= v0
|
v15 ^= v0
|
||||||
v15 = v15<<(64-16) | v15>>16
|
v15 = bits.RotateLeft64(v15, -16)
|
||||||
v10 += v15
|
v10 += v15
|
||||||
v5 ^= v10
|
v5 ^= v10
|
||||||
v5 = v5<<(64-63) | v5>>63
|
v5 = bits.RotateLeft64(v5, -63)
|
||||||
v1 += m[s[13]]
|
v1 += m[s[13]]
|
||||||
v1 += v6
|
v1 += v6
|
||||||
v12 ^= v1
|
v12 ^= v1
|
||||||
v12 = v12<<(64-16) | v12>>16
|
v12 = bits.RotateLeft64(v12, -16)
|
||||||
v11 += v12
|
v11 += v12
|
||||||
v6 ^= v11
|
v6 ^= v11
|
||||||
v6 = v6<<(64-63) | v6>>63
|
v6 = bits.RotateLeft64(v6, -63)
|
||||||
v2 += m[s[14]]
|
v2 += m[s[14]]
|
||||||
v2 += v7
|
v2 += v7
|
||||||
v13 ^= v2
|
v13 ^= v2
|
||||||
v13 = v13<<(64-16) | v13>>16
|
v13 = bits.RotateLeft64(v13, -16)
|
||||||
v8 += v13
|
v8 += v13
|
||||||
v7 ^= v8
|
v7 ^= v8
|
||||||
v7 = v7<<(64-63) | v7>>63
|
v7 = bits.RotateLeft64(v7, -63)
|
||||||
v3 += m[s[15]]
|
v3 += m[s[15]]
|
||||||
v3 += v4
|
v3 += v4
|
||||||
v14 ^= v3
|
v14 ^= v3
|
||||||
v14 = v14<<(64-16) | v14>>16
|
v14 = bits.RotateLeft64(v14, -16)
|
||||||
v9 += v14
|
v9 += v14
|
||||||
v4 ^= v9
|
v4 ^= v9
|
||||||
v4 = v4<<(64-63) | v4>>63
|
v4 = bits.RotateLeft64(v4, -63)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ package scrypt // import "golang.org/x/crypto/scrypt"
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"errors"
|
"errors"
|
||||||
|
"math/bits"
|
||||||
|
|
||||||
"golang.org/x/crypto/pbkdf2"
|
"golang.org/x/crypto/pbkdf2"
|
||||||
)
|
)
|
||||||
|
@ -52,77 +53,45 @@ func salsaXOR(tmp *[16]uint32, in, out []uint32) {
|
||||||
x9, x10, x11, x12, x13, x14, x15 := w9, w10, w11, w12, w13, w14, w15
|
x9, x10, x11, x12, x13, x14, x15 := w9, w10, w11, w12, w13, w14, w15
|
||||||
|
|
||||||
for i := 0; i < 8; i += 2 {
|
for i := 0; i < 8; i += 2 {
|
||||||
u := x0 + x12
|
x4 ^= bits.RotateLeft32(x0+x12, 7)
|
||||||
x4 ^= u<<7 | u>>(32-7)
|
x8 ^= bits.RotateLeft32(x4+x0, 9)
|
||||||
u = x4 + x0
|
x12 ^= bits.RotateLeft32(x8+x4, 13)
|
||||||
x8 ^= u<<9 | u>>(32-9)
|
x0 ^= bits.RotateLeft32(x12+x8, 18)
|
||||||
u = x8 + x4
|
|
||||||
x12 ^= u<<13 | u>>(32-13)
|
|
||||||
u = x12 + x8
|
|
||||||
x0 ^= u<<18 | u>>(32-18)
|
|
||||||
|
|
||||||
u = x5 + x1
|
x9 ^= bits.RotateLeft32(x5+x1, 7)
|
||||||
x9 ^= u<<7 | u>>(32-7)
|
x13 ^= bits.RotateLeft32(x9+x5, 9)
|
||||||
u = x9 + x5
|
x1 ^= bits.RotateLeft32(x13+x9, 13)
|
||||||
x13 ^= u<<9 | u>>(32-9)
|
x5 ^= bits.RotateLeft32(x1+x13, 18)
|
||||||
u = x13 + x9
|
|
||||||
x1 ^= u<<13 | u>>(32-13)
|
|
||||||
u = x1 + x13
|
|
||||||
x5 ^= u<<18 | u>>(32-18)
|
|
||||||
|
|
||||||
u = x10 + x6
|
x14 ^= bits.RotateLeft32(x10+x6, 7)
|
||||||
x14 ^= u<<7 | u>>(32-7)
|
x2 ^= bits.RotateLeft32(x14+x10, 9)
|
||||||
u = x14 + x10
|
x6 ^= bits.RotateLeft32(x2+x14, 13)
|
||||||
x2 ^= u<<9 | u>>(32-9)
|
x10 ^= bits.RotateLeft32(x6+x2, 18)
|
||||||
u = x2 + x14
|
|
||||||
x6 ^= u<<13 | u>>(32-13)
|
|
||||||
u = x6 + x2
|
|
||||||
x10 ^= u<<18 | u>>(32-18)
|
|
||||||
|
|
||||||
u = x15 + x11
|
x3 ^= bits.RotateLeft32(x15+x11, 7)
|
||||||
x3 ^= u<<7 | u>>(32-7)
|
x7 ^= bits.RotateLeft32(x3+x15, 9)
|
||||||
u = x3 + x15
|
x11 ^= bits.RotateLeft32(x7+x3, 13)
|
||||||
x7 ^= u<<9 | u>>(32-9)
|
x15 ^= bits.RotateLeft32(x11+x7, 18)
|
||||||
u = x7 + x3
|
|
||||||
x11 ^= u<<13 | u>>(32-13)
|
|
||||||
u = x11 + x7
|
|
||||||
x15 ^= u<<18 | u>>(32-18)
|
|
||||||
|
|
||||||
u = x0 + x3
|
x1 ^= bits.RotateLeft32(x0+x3, 7)
|
||||||
x1 ^= u<<7 | u>>(32-7)
|
x2 ^= bits.RotateLeft32(x1+x0, 9)
|
||||||
u = x1 + x0
|
x3 ^= bits.RotateLeft32(x2+x1, 13)
|
||||||
x2 ^= u<<9 | u>>(32-9)
|
x0 ^= bits.RotateLeft32(x3+x2, 18)
|
||||||
u = x2 + x1
|
|
||||||
x3 ^= u<<13 | u>>(32-13)
|
|
||||||
u = x3 + x2
|
|
||||||
x0 ^= u<<18 | u>>(32-18)
|
|
||||||
|
|
||||||
u = x5 + x4
|
x6 ^= bits.RotateLeft32(x5+x4, 7)
|
||||||
x6 ^= u<<7 | u>>(32-7)
|
x7 ^= bits.RotateLeft32(x6+x5, 9)
|
||||||
u = x6 + x5
|
x4 ^= bits.RotateLeft32(x7+x6, 13)
|
||||||
x7 ^= u<<9 | u>>(32-9)
|
x5 ^= bits.RotateLeft32(x4+x7, 18)
|
||||||
u = x7 + x6
|
|
||||||
x4 ^= u<<13 | u>>(32-13)
|
|
||||||
u = x4 + x7
|
|
||||||
x5 ^= u<<18 | u>>(32-18)
|
|
||||||
|
|
||||||
u = x10 + x9
|
x11 ^= bits.RotateLeft32(x10+x9, 7)
|
||||||
x11 ^= u<<7 | u>>(32-7)
|
x8 ^= bits.RotateLeft32(x11+x10, 9)
|
||||||
u = x11 + x10
|
x9 ^= bits.RotateLeft32(x8+x11, 13)
|
||||||
x8 ^= u<<9 | u>>(32-9)
|
x10 ^= bits.RotateLeft32(x9+x8, 18)
|
||||||
u = x8 + x11
|
|
||||||
x9 ^= u<<13 | u>>(32-13)
|
|
||||||
u = x9 + x8
|
|
||||||
x10 ^= u<<18 | u>>(32-18)
|
|
||||||
|
|
||||||
u = x15 + x14
|
x12 ^= bits.RotateLeft32(x15+x14, 7)
|
||||||
x12 ^= u<<7 | u>>(32-7)
|
x13 ^= bits.RotateLeft32(x12+x15, 9)
|
||||||
u = x12 + x15
|
x14 ^= bits.RotateLeft32(x13+x12, 13)
|
||||||
x13 ^= u<<9 | u>>(32-9)
|
x15 ^= bits.RotateLeft32(x14+x13, 18)
|
||||||
u = x13 + x12
|
|
||||||
x14 ^= u<<13 | u>>(32-13)
|
|
||||||
u = x14 + x13
|
|
||||||
x15 ^= u<<18 | u>>(32-18)
|
|
||||||
}
|
}
|
||||||
x0 += w0
|
x0 += w0
|
||||||
x1 += w1
|
x1 += w1
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//+build gccgo appengine !s390x
|
// +build gccgo appengine !s390x
|
||||||
|
|
||||||
package sha3
|
package sha3
|
||||||
|
|
||||||
|
|
|
@ -38,8 +38,9 @@ type state struct {
|
||||||
// [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf
|
// [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf
|
||||||
// "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and
|
// "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and
|
||||||
// Extendable-Output Functions (May 2014)"
|
// Extendable-Output Functions (May 2014)"
|
||||||
dsbyte byte
|
dsbyte byte
|
||||||
storage [maxRate]byte
|
|
||||||
|
storage storageBuf
|
||||||
|
|
||||||
// Specific to SHA-3 and SHAKE.
|
// Specific to SHA-3 and SHAKE.
|
||||||
outputLen int // the default output size in bytes
|
outputLen int // the default output size in bytes
|
||||||
|
@ -60,15 +61,15 @@ func (d *state) Reset() {
|
||||||
d.a[i] = 0
|
d.a[i] = 0
|
||||||
}
|
}
|
||||||
d.state = spongeAbsorbing
|
d.state = spongeAbsorbing
|
||||||
d.buf = d.storage[:0]
|
d.buf = d.storage.asBytes()[:0]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *state) clone() *state {
|
func (d *state) clone() *state {
|
||||||
ret := *d
|
ret := *d
|
||||||
if ret.state == spongeAbsorbing {
|
if ret.state == spongeAbsorbing {
|
||||||
ret.buf = ret.storage[:len(ret.buf)]
|
ret.buf = ret.storage.asBytes()[:len(ret.buf)]
|
||||||
} else {
|
} else {
|
||||||
ret.buf = ret.storage[d.rate-cap(d.buf) : d.rate]
|
ret.buf = ret.storage.asBytes()[d.rate-cap(d.buf) : d.rate]
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ret
|
return &ret
|
||||||
|
@ -82,13 +83,13 @@ func (d *state) permute() {
|
||||||
// If we're absorbing, we need to xor the input into the state
|
// If we're absorbing, we need to xor the input into the state
|
||||||
// before applying the permutation.
|
// before applying the permutation.
|
||||||
xorIn(d, d.buf)
|
xorIn(d, d.buf)
|
||||||
d.buf = d.storage[:0]
|
d.buf = d.storage.asBytes()[:0]
|
||||||
keccakF1600(&d.a)
|
keccakF1600(&d.a)
|
||||||
case spongeSqueezing:
|
case spongeSqueezing:
|
||||||
// If we're squeezing, we need to apply the permutatin before
|
// If we're squeezing, we need to apply the permutatin before
|
||||||
// copying more output.
|
// copying more output.
|
||||||
keccakF1600(&d.a)
|
keccakF1600(&d.a)
|
||||||
d.buf = d.storage[:d.rate]
|
d.buf = d.storage.asBytes()[:d.rate]
|
||||||
copyOut(d, d.buf)
|
copyOut(d, d.buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,7 +98,7 @@ func (d *state) permute() {
|
||||||
// the multi-bitrate 10..1 padding rule, and permutes the state.
|
// the multi-bitrate 10..1 padding rule, and permutes the state.
|
||||||
func (d *state) padAndPermute(dsbyte byte) {
|
func (d *state) padAndPermute(dsbyte byte) {
|
||||||
if d.buf == nil {
|
if d.buf == nil {
|
||||||
d.buf = d.storage[:0]
|
d.buf = d.storage.asBytes()[:0]
|
||||||
}
|
}
|
||||||
// Pad with this instance's domain-separator bits. We know that there's
|
// Pad with this instance's domain-separator bits. We know that there's
|
||||||
// at least one byte of space in d.buf because, if it were full,
|
// at least one byte of space in d.buf because, if it were full,
|
||||||
|
@ -105,7 +106,7 @@ func (d *state) padAndPermute(dsbyte byte) {
|
||||||
// first one bit for the padding. See the comment in the state struct.
|
// first one bit for the padding. See the comment in the state struct.
|
||||||
d.buf = append(d.buf, dsbyte)
|
d.buf = append(d.buf, dsbyte)
|
||||||
zerosStart := len(d.buf)
|
zerosStart := len(d.buf)
|
||||||
d.buf = d.storage[:d.rate]
|
d.buf = d.storage.asBytes()[:d.rate]
|
||||||
for i := zerosStart; i < d.rate; i++ {
|
for i := zerosStart; i < d.rate; i++ {
|
||||||
d.buf[i] = 0
|
d.buf[i] = 0
|
||||||
}
|
}
|
||||||
|
@ -116,7 +117,7 @@ func (d *state) padAndPermute(dsbyte byte) {
|
||||||
// Apply the permutation
|
// Apply the permutation
|
||||||
d.permute()
|
d.permute()
|
||||||
d.state = spongeSqueezing
|
d.state = spongeSqueezing
|
||||||
d.buf = d.storage[:d.rate]
|
d.buf = d.storage.asBytes()[:d.rate]
|
||||||
copyOut(d, d.buf)
|
copyOut(d, d.buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +128,7 @@ func (d *state) Write(p []byte) (written int, err error) {
|
||||||
panic("sha3: write to sponge after read")
|
panic("sha3: write to sponge after read")
|
||||||
}
|
}
|
||||||
if d.buf == nil {
|
if d.buf == nil {
|
||||||
d.buf = d.storage[:0]
|
d.buf = d.storage.asBytes()[:0]
|
||||||
}
|
}
|
||||||
written = len(p)
|
written = len(p)
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//+build !gccgo,!appengine
|
// +build !gccgo,!appengine
|
||||||
|
|
||||||
package sha3
|
package sha3
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ func (s *asmState) Write(b []byte) (int, error) {
|
||||||
if len(s.buf) == 0 && len(b) >= cap(s.buf) {
|
if len(s.buf) == 0 && len(b) >= cap(s.buf) {
|
||||||
// Hash the data directly and push any remaining bytes
|
// Hash the data directly and push any remaining bytes
|
||||||
// into the buffer.
|
// into the buffer.
|
||||||
remainder := len(s.buf) % s.rate
|
remainder := len(b) % s.rate
|
||||||
kimd(s.function, &s.a, b[:len(b)-remainder])
|
kimd(s.function, &s.a, b[:len(b)-remainder])
|
||||||
if remainder != 0 {
|
if remainder != 0 {
|
||||||
s.copyIntoBuf(b[len(b)-remainder:])
|
s.copyIntoBuf(b[len(b)-remainder:])
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//+build !gccgo,!appengine
|
// +build !gccgo,!appengine
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ type ShakeHash interface {
|
||||||
|
|
||||||
// cSHAKE specific context
|
// cSHAKE specific context
|
||||||
type cshakeState struct {
|
type cshakeState struct {
|
||||||
state // SHA-3 state context and Read/Write operations
|
*state // SHA-3 state context and Read/Write operations
|
||||||
|
|
||||||
// initBlock is the cSHAKE specific initialization set of bytes. It is initialized
|
// initBlock is the cSHAKE specific initialization set of bytes. It is initialized
|
||||||
// by newCShake function and stores concatenation of N followed by S, encoded
|
// by newCShake function and stores concatenation of N followed by S, encoded
|
||||||
|
@ -82,7 +82,7 @@ func leftEncode(value uint64) []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
func newCShake(N, S []byte, rate int, dsbyte byte) ShakeHash {
|
func newCShake(N, S []byte, rate int, dsbyte byte) ShakeHash {
|
||||||
c := cshakeState{state: state{rate: rate, dsbyte: dsbyte}}
|
c := cshakeState{state: &state{rate: rate, dsbyte: dsbyte}}
|
||||||
|
|
||||||
// leftEncode returns max 9 bytes
|
// leftEncode returns max 9 bytes
|
||||||
c.initBlock = make([]byte, 0, 9*2+len(N)+len(S))
|
c.initBlock = make([]byte, 0, 9*2+len(N)+len(S))
|
||||||
|
@ -104,7 +104,7 @@ func (c *cshakeState) Reset() {
|
||||||
func (c *cshakeState) Clone() ShakeHash {
|
func (c *cshakeState) Clone() ShakeHash {
|
||||||
b := make([]byte, len(c.initBlock))
|
b := make([]byte, len(c.initBlock))
|
||||||
copy(b, c.initBlock)
|
copy(b, c.initBlock)
|
||||||
return &cshakeState{state: *c.clone(), initBlock: b}
|
return &cshakeState{state: c.clone(), initBlock: b}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clone returns copy of SHAKE context within its current state.
|
// Clone returns copy of SHAKE context within its current state.
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//+build gccgo appengine !s390x
|
// +build gccgo appengine !s390x
|
||||||
|
|
||||||
package sha3
|
package sha3
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,13 @@
|
||||||
|
|
||||||
package sha3
|
package sha3
|
||||||
|
|
||||||
|
// A storageBuf is an aligned array of maxRate bytes.
|
||||||
|
type storageBuf [maxRate]byte
|
||||||
|
|
||||||
|
func (b *storageBuf) asBytes() *[maxRate]byte {
|
||||||
|
return (*[maxRate]byte)(b)
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
xorIn = xorInGeneric
|
xorIn = xorInGeneric
|
||||||
copyOut = copyOutGeneric
|
copyOut = copyOutGeneric
|
||||||
|
|
|
@ -9,9 +9,16 @@ package sha3
|
||||||
|
|
||||||
import "unsafe"
|
import "unsafe"
|
||||||
|
|
||||||
|
// A storageBuf is an aligned array of maxRate bytes.
|
||||||
|
type storageBuf [maxRate / 8]uint64
|
||||||
|
|
||||||
|
func (b *storageBuf) asBytes() *[maxRate]byte {
|
||||||
|
return (*[maxRate]byte)(unsafe.Pointer(b))
|
||||||
|
}
|
||||||
|
|
||||||
func xorInUnaligned(d *state, buf []byte) {
|
func xorInUnaligned(d *state, buf []byte) {
|
||||||
bw := (*[maxRate / 8]uint64)(unsafe.Pointer(&buf[0]))
|
|
||||||
n := len(buf)
|
n := len(buf)
|
||||||
|
bw := (*[maxRate / 8]uint64)(unsafe.Pointer(&buf[0]))[: n/8 : n/8]
|
||||||
if n >= 72 {
|
if n >= 72 {
|
||||||
d.a[0] ^= bw[0]
|
d.a[0] ^= bw[0]
|
||||||
d.a[1] ^= bw[1]
|
d.a[1] ^= bw[1]
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !gccgo
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// System calls for ppc64, AIX are implemented in runtime/syscall_aix.go
|
||||||
|
//
|
||||||
|
|
||||||
|
TEXT ·syscall6(SB),NOSPLIT,$0-88
|
||||||
|
JMP syscall·syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·rawSyscall6(SB),NOSPLIT,$0-88
|
||||||
|
JMP syscall·rawSyscall6(SB)
|
|
@ -6,8 +6,6 @@
|
||||||
|
|
||||||
package cpu
|
package cpu
|
||||||
|
|
||||||
import "golang.org/x/sys/unix"
|
|
||||||
|
|
||||||
const cacheLineSize = 128
|
const cacheLineSize = 128
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -18,7 +16,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
impl := unix.Getsystemcfg(_SC_IMPL)
|
impl := getsystemcfg(_SC_IMPL)
|
||||||
if impl&_IMPL_POWER8 != 0 {
|
if impl&_IMPL_POWER8 != 0 {
|
||||||
PPC64.IsPOWER8 = true
|
PPC64.IsPOWER8 = true
|
||||||
}
|
}
|
||||||
|
@ -28,3 +26,9 @@ func init() {
|
||||||
|
|
||||||
Initialized = true
|
Initialized = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getsystemcfg(label int) (n uint64) {
|
||||||
|
r0, _ := callgetsystemcfg(label)
|
||||||
|
n = uint64(r0)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Minimal copy of x/sys/unix so the cpu package can make a
|
||||||
|
// system call on AIX without depending on x/sys/unix.
|
||||||
|
// (See golang.org/issue/32102)
|
||||||
|
|
||||||
|
// +build aix,ppc64
|
||||||
|
// +build !gccgo
|
||||||
|
|
||||||
|
package cpu
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:cgo_import_dynamic libc_getsystemcfg getsystemcfg "libc.a/shr_64.o"
|
||||||
|
|
||||||
|
//go:linkname libc_getsystemcfg libc_getsystemcfg
|
||||||
|
|
||||||
|
type syscallFunc uintptr
|
||||||
|
|
||||||
|
var libc_getsystemcfg syscallFunc
|
||||||
|
|
||||||
|
type errno = syscall.Errno
|
||||||
|
|
||||||
|
// Implemented in runtime/syscall_aix.go.
|
||||||
|
func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err errno)
|
||||||
|
func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err errno)
|
||||||
|
|
||||||
|
func callgetsystemcfg(label int) (r1 uintptr, e1 errno) {
|
||||||
|
r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_getsystemcfg)), 1, uintptr(label), 0, 0, 0, 0, 0)
|
||||||
|
return
|
||||||
|
}
|
|
@ -7,6 +7,7 @@
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math/bits"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -79,46 +80,7 @@ func (s *CPUSet) IsSet(cpu int) bool {
|
||||||
func (s *CPUSet) Count() int {
|
func (s *CPUSet) Count() int {
|
||||||
c := 0
|
c := 0
|
||||||
for _, b := range s {
|
for _, b := range s {
|
||||||
c += onesCount64(uint64(b))
|
c += bits.OnesCount64(uint64(b))
|
||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// onesCount64 is a copy of Go 1.9's math/bits.OnesCount64.
|
|
||||||
// Once this package can require Go 1.9, we can delete this
|
|
||||||
// and update the caller to use bits.OnesCount64.
|
|
||||||
func onesCount64(x uint64) int {
|
|
||||||
const m0 = 0x5555555555555555 // 01010101 ...
|
|
||||||
const m1 = 0x3333333333333333 // 00110011 ...
|
|
||||||
const m2 = 0x0f0f0f0f0f0f0f0f // 00001111 ...
|
|
||||||
const m3 = 0x00ff00ff00ff00ff // etc.
|
|
||||||
const m4 = 0x0000ffff0000ffff
|
|
||||||
|
|
||||||
// Implementation: Parallel summing of adjacent bits.
|
|
||||||
// See "Hacker's Delight", Chap. 5: Counting Bits.
|
|
||||||
// The following pattern shows the general approach:
|
|
||||||
//
|
|
||||||
// x = x>>1&(m0&m) + x&(m0&m)
|
|
||||||
// x = x>>2&(m1&m) + x&(m1&m)
|
|
||||||
// x = x>>4&(m2&m) + x&(m2&m)
|
|
||||||
// x = x>>8&(m3&m) + x&(m3&m)
|
|
||||||
// x = x>>16&(m4&m) + x&(m4&m)
|
|
||||||
// x = x>>32&(m5&m) + x&(m5&m)
|
|
||||||
// return int(x)
|
|
||||||
//
|
|
||||||
// Masking (& operations) can be left away when there's no
|
|
||||||
// danger that a field's sum will carry over into the next
|
|
||||||
// field: Since the result cannot be > 64, 8 bits is enough
|
|
||||||
// and we can ignore the masks for the shifts by 8 and up.
|
|
||||||
// Per "Hacker's Delight", the first line can be simplified
|
|
||||||
// more, but it saves at best one instruction, so we leave
|
|
||||||
// it alone for clarity.
|
|
||||||
const m = 1<<64 - 1
|
|
||||||
x = x>>1&(m0&m) + x&(m0&m)
|
|
||||||
x = x>>2&(m1&m) + x&(m1&m)
|
|
||||||
x = (x>>4 + x) & (m2 & m)
|
|
||||||
x += x >> 8
|
|
||||||
x += x >> 16
|
|
||||||
x += x >> 32
|
|
||||||
return int(x) & (1<<7 - 1)
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build riscv64,!gccgo
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// System calls for linux/riscv64.
|
||||||
|
//
|
||||||
|
// Where available, just jump to package syscall's implementation of
|
||||||
|
// these functions.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
CALL runtime·entersyscall(SB)
|
||||||
|
MOV a1+8(FP), A0
|
||||||
|
MOV a2+16(FP), A1
|
||||||
|
MOV a3+24(FP), A2
|
||||||
|
MOV $0, A3
|
||||||
|
MOV $0, A4
|
||||||
|
MOV $0, A5
|
||||||
|
MOV $0, A6
|
||||||
|
MOV trap+0(FP), A7 // syscall entry
|
||||||
|
ECALL
|
||||||
|
MOV A0, r1+32(FP) // r1
|
||||||
|
MOV A1, r2+40(FP) // r2
|
||||||
|
CALL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·RawSyscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
|
||||||
|
MOV a1+8(FP), A0
|
||||||
|
MOV a2+16(FP), A1
|
||||||
|
MOV a3+24(FP), A2
|
||||||
|
MOV ZERO, A3
|
||||||
|
MOV ZERO, A4
|
||||||
|
MOV ZERO, A5
|
||||||
|
MOV trap+0(FP), A7 // syscall entry
|
||||||
|
ECALL
|
||||||
|
MOV A0, r1+32(FP)
|
||||||
|
MOV A1, r2+40(FP)
|
||||||
|
RET
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !gccgo
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// System call support for arm64, OpenBSD
|
||||||
|
//
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall9(SB),NOSPLIT,$0-104
|
||||||
|
JMP syscall·Syscall9(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·RawSyscall6(SB)
|
|
@ -2,16 +2,101 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris
|
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
import "syscall"
|
import "unsafe"
|
||||||
|
|
||||||
|
// readInt returns the size-bytes unsigned integer in native byte order at offset off.
|
||||||
|
func readInt(b []byte, off, size uintptr) (u uint64, ok bool) {
|
||||||
|
if len(b) < int(off+size) {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
if isBigEndian {
|
||||||
|
return readIntBE(b[off:], size), true
|
||||||
|
}
|
||||||
|
return readIntLE(b[off:], size), true
|
||||||
|
}
|
||||||
|
|
||||||
|
func readIntBE(b []byte, size uintptr) uint64 {
|
||||||
|
switch size {
|
||||||
|
case 1:
|
||||||
|
return uint64(b[0])
|
||||||
|
case 2:
|
||||||
|
_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
|
||||||
|
return uint64(b[1]) | uint64(b[0])<<8
|
||||||
|
case 4:
|
||||||
|
_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
|
||||||
|
return uint64(b[3]) | uint64(b[2])<<8 | uint64(b[1])<<16 | uint64(b[0])<<24
|
||||||
|
case 8:
|
||||||
|
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
|
||||||
|
return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
|
||||||
|
uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
|
||||||
|
default:
|
||||||
|
panic("syscall: readInt with unsupported size")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func readIntLE(b []byte, size uintptr) uint64 {
|
||||||
|
switch size {
|
||||||
|
case 1:
|
||||||
|
return uint64(b[0])
|
||||||
|
case 2:
|
||||||
|
_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
|
||||||
|
return uint64(b[0]) | uint64(b[1])<<8
|
||||||
|
case 4:
|
||||||
|
_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
|
||||||
|
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24
|
||||||
|
case 8:
|
||||||
|
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
|
||||||
|
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
|
||||||
|
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
|
||||||
|
default:
|
||||||
|
panic("syscall: readInt with unsupported size")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ParseDirent parses up to max directory entries in buf,
|
// ParseDirent parses up to max directory entries in buf,
|
||||||
// appending the names to names. It returns the number of
|
// appending the names to names. It returns the number of
|
||||||
// bytes consumed from buf, the number of entries added
|
// bytes consumed from buf, the number of entries added
|
||||||
// to names, and the new names slice.
|
// to names, and the new names slice.
|
||||||
func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
|
func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
|
||||||
return syscall.ParseDirent(buf, max, names)
|
origlen := len(buf)
|
||||||
|
count = 0
|
||||||
|
for max != 0 && len(buf) > 0 {
|
||||||
|
reclen, ok := direntReclen(buf)
|
||||||
|
if !ok || reclen > uint64(len(buf)) {
|
||||||
|
return origlen, count, names
|
||||||
|
}
|
||||||
|
rec := buf[:reclen]
|
||||||
|
buf = buf[reclen:]
|
||||||
|
ino, ok := direntIno(rec)
|
||||||
|
if !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if ino == 0 { // File absent in directory.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const namoff = uint64(unsafe.Offsetof(Dirent{}.Name))
|
||||||
|
namlen, ok := direntNamlen(rec)
|
||||||
|
if !ok || namoff+namlen > uint64(len(rec)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
name := rec[namoff : namoff+namlen]
|
||||||
|
for i, c := range name {
|
||||||
|
if c == 0 {
|
||||||
|
name = name[:i]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check for useless names before allocating a string.
|
||||||
|
if string(name) == "." || string(name) == ".." {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
max--
|
||||||
|
count++
|
||||||
|
names = append(names, string(name))
|
||||||
|
}
|
||||||
|
return origlen - len(buf), count, names
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
//
|
//
|
||||||
// +build 386 amd64 amd64p32 arm arm64 ppc64le mipsle mips64le
|
// +build 386 amd64 amd64p32 arm arm64 ppc64le mipsle mips64le riscv64
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,19 @@
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
import "runtime"
|
import (
|
||||||
|
"runtime"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ioctl itself should not be exposed directly, but additional get/set
|
||||||
|
// functions for specific types are permissible.
|
||||||
|
|
||||||
|
// IoctlSetInt performs an ioctl operation which sets an integer value
|
||||||
|
// on fd, using the specified request number.
|
||||||
|
func IoctlSetInt(fd int, req uint, value int) error {
|
||||||
|
return ioctl(fd, req, uintptr(value))
|
||||||
|
}
|
||||||
|
|
||||||
// IoctlSetWinsize performs an ioctl on fd with a *Winsize argument.
|
// IoctlSetWinsize performs an ioctl on fd with a *Winsize argument.
|
||||||
//
|
//
|
||||||
|
@ -14,7 +26,7 @@ import "runtime"
|
||||||
func IoctlSetWinsize(fd int, req uint, value *Winsize) error {
|
func IoctlSetWinsize(fd int, req uint, value *Winsize) error {
|
||||||
// TODO: if we get the chance, remove the req parameter and
|
// TODO: if we get the chance, remove the req parameter and
|
||||||
// hardcode TIOCSWINSZ.
|
// hardcode TIOCSWINSZ.
|
||||||
err := ioctlSetWinsize(fd, req, value)
|
err := ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
||||||
runtime.KeepAlive(value)
|
runtime.KeepAlive(value)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -24,7 +36,30 @@ func IoctlSetWinsize(fd int, req uint, value *Winsize) error {
|
||||||
// The req value will usually be TCSETA or TIOCSETA.
|
// The req value will usually be TCSETA or TIOCSETA.
|
||||||
func IoctlSetTermios(fd int, req uint, value *Termios) error {
|
func IoctlSetTermios(fd int, req uint, value *Termios) error {
|
||||||
// TODO: if we get the chance, remove the req parameter.
|
// TODO: if we get the chance, remove the req parameter.
|
||||||
err := ioctlSetTermios(fd, req, value)
|
err := ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
||||||
runtime.KeepAlive(value)
|
runtime.KeepAlive(value)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IoctlGetInt performs an ioctl operation which gets an integer value
|
||||||
|
// from fd, using the specified request number.
|
||||||
|
//
|
||||||
|
// A few ioctl requests use the return value as an output parameter;
|
||||||
|
// for those, IoctlRetInt should be used instead of this function.
|
||||||
|
func IoctlGetInt(fd int, req uint) (int, error) {
|
||||||
|
var value int
|
||||||
|
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
||||||
|
return value, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
|
||||||
|
var value Winsize
|
||||||
|
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
||||||
|
return &value, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
|
||||||
|
var value Termios
|
||||||
|
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
||||||
|
return &value, err
|
||||||
|
}
|
||||||
|
|
|
@ -105,25 +105,25 @@ dragonfly_amd64)
|
||||||
freebsd_386)
|
freebsd_386)
|
||||||
mkerrors="$mkerrors -m32"
|
mkerrors="$mkerrors -m32"
|
||||||
mksyscall="go run mksyscall.go -l32"
|
mksyscall="go run mksyscall.go -l32"
|
||||||
mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master'"
|
mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/11/sys/kern/syscalls.master'"
|
||||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
;;
|
;;
|
||||||
freebsd_amd64)
|
freebsd_amd64)
|
||||||
mkerrors="$mkerrors -m64"
|
mkerrors="$mkerrors -m64"
|
||||||
mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master'"
|
mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/11/sys/kern/syscalls.master'"
|
||||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
;;
|
;;
|
||||||
freebsd_arm)
|
freebsd_arm)
|
||||||
mkerrors="$mkerrors"
|
mkerrors="$mkerrors"
|
||||||
mksyscall="go run mksyscall.go -l32 -arm"
|
mksyscall="go run mksyscall.go -l32 -arm"
|
||||||
mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master'"
|
mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/11/sys/kern/syscalls.master'"
|
||||||
# Let the type of C char be signed for making the bare syscall
|
# Let the type of C char be signed for making the bare syscall
|
||||||
# API consistent across platforms.
|
# API consistent across platforms.
|
||||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
||||||
;;
|
;;
|
||||||
freebsd_arm64)
|
freebsd_arm64)
|
||||||
mkerrors="$mkerrors -m64"
|
mkerrors="$mkerrors -m64"
|
||||||
mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master'"
|
mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/11/sys/kern/syscalls.master'"
|
||||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
;;
|
;;
|
||||||
netbsd_386)
|
netbsd_386)
|
||||||
|
@ -146,24 +146,39 @@ netbsd_arm)
|
||||||
# API consistent across platforms.
|
# API consistent across platforms.
|
||||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
||||||
;;
|
;;
|
||||||
|
netbsd_arm64)
|
||||||
|
mkerrors="$mkerrors -m64"
|
||||||
|
mksyscall="go run mksyscall.go -netbsd"
|
||||||
|
mksysnum="go run mksysnum.go 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master'"
|
||||||
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
|
;;
|
||||||
openbsd_386)
|
openbsd_386)
|
||||||
mkerrors="$mkerrors -m32"
|
mkerrors="$mkerrors -m32"
|
||||||
mksyscall="go run mksyscall.go -l32 -openbsd"
|
mksyscall="go run mksyscall.go -l32 -openbsd"
|
||||||
mksysctl="./mksysctl_openbsd.pl"
|
mksysctl="go run mksysctl_openbsd.go"
|
||||||
mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'"
|
mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'"
|
||||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
;;
|
;;
|
||||||
openbsd_amd64)
|
openbsd_amd64)
|
||||||
mkerrors="$mkerrors -m64"
|
mkerrors="$mkerrors -m64"
|
||||||
mksyscall="go run mksyscall.go -openbsd"
|
mksyscall="go run mksyscall.go -openbsd"
|
||||||
mksysctl="./mksysctl_openbsd.pl"
|
mksysctl="go run mksysctl_openbsd.go"
|
||||||
mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'"
|
mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'"
|
||||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
;;
|
;;
|
||||||
openbsd_arm)
|
openbsd_arm)
|
||||||
mkerrors="$mkerrors"
|
mkerrors="$mkerrors"
|
||||||
mksyscall="go run mksyscall.go -l32 -openbsd -arm"
|
mksyscall="go run mksyscall.go -l32 -openbsd -arm"
|
||||||
mksysctl="./mksysctl_openbsd.pl"
|
mksysctl="go run mksysctl_openbsd.go"
|
||||||
|
mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'"
|
||||||
|
# Let the type of C char be signed for making the bare syscall
|
||||||
|
# API consistent across platforms.
|
||||||
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
||||||
|
;;
|
||||||
|
openbsd_arm64)
|
||||||
|
mkerrors="$mkerrors -m64"
|
||||||
|
mksyscall="go run mksyscall.go -openbsd"
|
||||||
|
mksysctl="go run mksysctl_openbsd.go"
|
||||||
mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'"
|
mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'"
|
||||||
# Let the type of C char be signed for making the bare syscall
|
# Let the type of C char be signed for making the bare syscall
|
||||||
# API consistent across platforms.
|
# API consistent across platforms.
|
||||||
|
|
|
@ -182,6 +182,8 @@ struct ltchars {
|
||||||
#include <sys/signalfd.h>
|
#include <sys/signalfd.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/xattr.h>
|
#include <sys/xattr.h>
|
||||||
|
#include <linux/bpf.h>
|
||||||
|
#include <linux/capability.h>
|
||||||
#include <linux/errqueue.h>
|
#include <linux/errqueue.h>
|
||||||
#include <linux/if.h>
|
#include <linux/if.h>
|
||||||
#include <linux/if_alg.h>
|
#include <linux/if_alg.h>
|
||||||
|
@ -197,12 +199,14 @@ struct ltchars {
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/kexec.h>
|
#include <linux/kexec.h>
|
||||||
#include <linux/keyctl.h>
|
#include <linux/keyctl.h>
|
||||||
|
#include <linux/loop.h>
|
||||||
#include <linux/magic.h>
|
#include <linux/magic.h>
|
||||||
#include <linux/memfd.h>
|
#include <linux/memfd.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/netfilter/nfnetlink.h>
|
#include <linux/netfilter/nfnetlink.h>
|
||||||
#include <linux/netlink.h>
|
#include <linux/netlink.h>
|
||||||
#include <linux/net_namespace.h>
|
#include <linux/net_namespace.h>
|
||||||
|
#include <linux/nsfs.h>
|
||||||
#include <linux/perf_event.h>
|
#include <linux/perf_event.h>
|
||||||
#include <linux/random.h>
|
#include <linux/random.h>
|
||||||
#include <linux/reboot.h>
|
#include <linux/reboot.h>
|
||||||
|
@ -222,6 +226,7 @@ struct ltchars {
|
||||||
#include <linux/hdreg.h>
|
#include <linux/hdreg.h>
|
||||||
#include <linux/rtc.h>
|
#include <linux/rtc.h>
|
||||||
#include <linux/if_xdp.h>
|
#include <linux/if_xdp.h>
|
||||||
|
#include <linux/cryptouser.h>
|
||||||
#include <mtd/ubi-user.h>
|
#include <mtd/ubi-user.h>
|
||||||
#include <net/route.h>
|
#include <net/route.h>
|
||||||
|
|
||||||
|
@ -432,7 +437,9 @@ ccflags="$@"
|
||||||
$2 ~ /^TC[IO](ON|OFF)$/ ||
|
$2 ~ /^TC[IO](ON|OFF)$/ ||
|
||||||
$2 ~ /^IN_/ ||
|
$2 ~ /^IN_/ ||
|
||||||
$2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
|
$2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
|
||||||
$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|ICMP6|TCP|EVFILT|NOTE|EV|SHUT|PROT|MAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ ||
|
$2 ~ /^LO_(KEY|NAME)_SIZE$/ ||
|
||||||
|
$2 ~ /^LOOP_(CLR|CTL|GET|SET)_/ ||
|
||||||
|
$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|ICMP6|TCP|MCAST|EVFILT|NOTE|EV|SHUT|PROT|MAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ ||
|
||||||
$2 ~ /^TP_STATUS_/ ||
|
$2 ~ /^TP_STATUS_/ ||
|
||||||
$2 ~ /^FALLOC_/ ||
|
$2 ~ /^FALLOC_/ ||
|
||||||
$2 == "ICMPV6_FILTER" ||
|
$2 == "ICMPV6_FILTER" ||
|
||||||
|
@ -445,6 +452,7 @@ ccflags="$@"
|
||||||
$2 ~ /^SYSCTL_VERS/ ||
|
$2 ~ /^SYSCTL_VERS/ ||
|
||||||
$2 !~ "MNT_BITS" &&
|
$2 !~ "MNT_BITS" &&
|
||||||
$2 ~ /^(MS|MNT|UMOUNT)_/ ||
|
$2 ~ /^(MS|MNT|UMOUNT)_/ ||
|
||||||
|
$2 ~ /^NS_GET_/ ||
|
||||||
$2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
|
$2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
|
||||||
$2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT)_/ ||
|
$2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT)_/ ||
|
||||||
$2 ~ /^KEXEC_/ ||
|
$2 ~ /^KEXEC_/ ||
|
||||||
|
@ -465,7 +473,7 @@ ccflags="$@"
|
||||||
$2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ ||
|
$2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ ||
|
||||||
$2 ~ /^PRIO_(PROCESS|PGRP|USER)/ ||
|
$2 ~ /^PRIO_(PROCESS|PGRP|USER)/ ||
|
||||||
$2 ~ /^CLONE_[A-Z_]+/ ||
|
$2 ~ /^CLONE_[A-Z_]+/ ||
|
||||||
$2 !~ /^(BPF_TIMEVAL)$/ &&
|
$2 !~ /^(BPF_TIMEVAL|BPF_FIB_LOOKUP_[A-Z]+)$/ &&
|
||||||
$2 ~ /^(BPF|DLT)_/ ||
|
$2 ~ /^(BPF|DLT)_/ ||
|
||||||
$2 ~ /^(CLOCK|TIMER)_/ ||
|
$2 ~ /^(CLOCK|TIMER)_/ ||
|
||||||
$2 ~ /^CAN_/ ||
|
$2 ~ /^CAN_/ ||
|
||||||
|
@ -499,6 +507,7 @@ ccflags="$@"
|
||||||
$2 ~ /^NFN/ ||
|
$2 ~ /^NFN/ ||
|
||||||
$2 ~ /^XDP_/ ||
|
$2 ~ /^XDP_/ ||
|
||||||
$2 ~ /^(HDIO|WIN|SMART)_/ ||
|
$2 ~ /^(HDIO|WIN|SMART)_/ ||
|
||||||
|
$2 ~ /^CRYPTO_/ ||
|
||||||
$2 !~ "WMESGLEN" &&
|
$2 !~ "WMESGLEN" &&
|
||||||
$2 ~ /^W[A-Z0-9]+$/ ||
|
$2 ~ /^W[A-Z0-9]+$/ ||
|
||||||
$2 ~/^PPPIOC/ ||
|
$2 ~/^PPPIOC/ ||
|
||||||
|
|
|
@ -42,9 +42,16 @@ func main() {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if goos == "aix" {
|
||||||
|
// Replace type of Atim, Mtim and Ctim by Timespec in Stat_t
|
||||||
|
// to avoid having both StTimespec and Timespec.
|
||||||
|
sttimespec := regexp.MustCompile(`_Ctype_struct_st_timespec`)
|
||||||
|
b = sttimespec.ReplaceAll(b, []byte("Timespec"))
|
||||||
|
}
|
||||||
|
|
||||||
// Intentionally export __val fields in Fsid and Sigset_t
|
// Intentionally export __val fields in Fsid and Sigset_t
|
||||||
valRegex := regexp.MustCompile(`type (Fsid|Sigset_t) struct {(\s+)X__val(\s+\S+\s+)}`)
|
valRegex := regexp.MustCompile(`type (Fsid|Sigset_t) struct {(\s+)X__(bits|val)(\s+\S+\s+)}`)
|
||||||
b = valRegex.ReplaceAll(b, []byte("type $1 struct {${2}Val$3}"))
|
b = valRegex.ReplaceAll(b, []byte("type $1 struct {${2}Val$4}"))
|
||||||
|
|
||||||
// Intentionally export __fds_bits field in FdSet
|
// Intentionally export __fds_bits field in FdSet
|
||||||
fdSetRegex := regexp.MustCompile(`type (FdSet) struct {(\s+)X__fds_bits(\s+\S+\s+)}`)
|
fdSetRegex := regexp.MustCompile(`type (FdSet) struct {(\s+)X__fds_bits(\s+\S+\s+)}`)
|
||||||
|
@ -96,6 +103,15 @@ func main() {
|
||||||
cgoCommandRegex := regexp.MustCompile(`(cgo -godefs .*)`)
|
cgoCommandRegex := regexp.MustCompile(`(cgo -godefs .*)`)
|
||||||
b = cgoCommandRegex.ReplaceAll(b, []byte(replacement))
|
b = cgoCommandRegex.ReplaceAll(b, []byte(replacement))
|
||||||
|
|
||||||
|
// Rename Stat_t time fields
|
||||||
|
if goos == "freebsd" && goarch == "386" {
|
||||||
|
// Hide Stat_t.[AMCB]tim_ext fields
|
||||||
|
renameStatTimeExtFieldsRegex := regexp.MustCompile(`[AMCB]tim_ext`)
|
||||||
|
b = renameStatTimeExtFieldsRegex.ReplaceAll(b, []byte("_"))
|
||||||
|
}
|
||||||
|
renameStatTimeFieldsRegex := regexp.MustCompile(`([AMCB])(?:irth)?time?(?:spec)?\s+(Timespec|StTimespec)`)
|
||||||
|
b = renameStatTimeFieldsRegex.ReplaceAll(b, []byte("${1}tim ${2}"))
|
||||||
|
|
||||||
// gofmt
|
// gofmt
|
||||||
b, err = format.Source(b)
|
b, err = format.Source(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -214,6 +214,11 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if funct != "fcntl" && funct != "FcntlInt" && funct != "readlen" && funct != "writelen" {
|
if funct != "fcntl" && funct != "FcntlInt" && funct != "readlen" && funct != "writelen" {
|
||||||
|
if sysname == "select" {
|
||||||
|
// select is a keyword of Go. Its name is
|
||||||
|
// changed to c_select.
|
||||||
|
cExtern += "#define c_select select\n"
|
||||||
|
}
|
||||||
// Imports of system calls from libc
|
// Imports of system calls from libc
|
||||||
cExtern += fmt.Sprintf("%s %s", cRettype, sysname)
|
cExtern += fmt.Sprintf("%s %s", cRettype, sysname)
|
||||||
cIn := strings.Join(cIn, ", ")
|
cIn := strings.Join(cIn, ", ")
|
||||||
|
@ -328,7 +333,13 @@ func main() {
|
||||||
} else {
|
} else {
|
||||||
call += ""
|
call += ""
|
||||||
}
|
}
|
||||||
call += fmt.Sprintf("C.%s(%s)", sysname, arglist)
|
if sysname == "select" {
|
||||||
|
// select is a keyword of Go. Its name is
|
||||||
|
// changed to c_select.
|
||||||
|
call += fmt.Sprintf("C.c_%s(%s)", sysname, arglist)
|
||||||
|
} else {
|
||||||
|
call += fmt.Sprintf("C.%s(%s)", sysname, arglist)
|
||||||
|
}
|
||||||
|
|
||||||
// Assign return values.
|
// Assign return values.
|
||||||
body := ""
|
body := ""
|
||||||
|
|
|
@ -282,6 +282,11 @@ func main() {
|
||||||
if !onlyCommon {
|
if !onlyCommon {
|
||||||
// GCCGO Prototype Generation
|
// GCCGO Prototype Generation
|
||||||
// Imports of system calls from libc
|
// Imports of system calls from libc
|
||||||
|
if sysname == "select" {
|
||||||
|
// select is a keyword of Go. Its name is
|
||||||
|
// changed to c_select.
|
||||||
|
cExtern += "#define c_select select\n"
|
||||||
|
}
|
||||||
cExtern += fmt.Sprintf("%s %s", cRettype, sysname)
|
cExtern += fmt.Sprintf("%s %s", cRettype, sysname)
|
||||||
cIn := strings.Join(cIn, ", ")
|
cIn := strings.Join(cIn, ", ")
|
||||||
cExtern += fmt.Sprintf("(%s);\n", cIn)
|
cExtern += fmt.Sprintf("(%s);\n", cIn)
|
||||||
|
@ -490,7 +495,14 @@ func main() {
|
||||||
|
|
||||||
// GCCGO function generation
|
// GCCGO function generation
|
||||||
argsgccgolist := strings.Join(argsgccgo, ", ")
|
argsgccgolist := strings.Join(argsgccgo, ", ")
|
||||||
callgccgo := fmt.Sprintf("C.%s(%s)", sysname, argsgccgolist)
|
var callgccgo string
|
||||||
|
if sysname == "select" {
|
||||||
|
// select is a keyword of Go. Its name is
|
||||||
|
// changed to c_select.
|
||||||
|
callgccgo = fmt.Sprintf("C.c_%s(%s)", sysname, argsgccgolist)
|
||||||
|
} else {
|
||||||
|
callgccgo = fmt.Sprintf("C.%s(%s)", sysname, argsgccgolist)
|
||||||
|
}
|
||||||
textgccgo += callProto
|
textgccgo += callProto
|
||||||
textgccgo += fmt.Sprintf("\tr1 = uintptr(%s)\n", callgccgo)
|
textgccgo += fmt.Sprintf("\tr1 = uintptr(%s)\n", callgccgo)
|
||||||
textgccgo += "\te1 = syscall.GetErrno()\n"
|
textgccgo += "\te1 = syscall.GetErrno()\n"
|
||||||
|
|
|
@ -0,0 +1,355 @@
|
||||||
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
// Parse the header files for OpenBSD and generate a Go usable sysctl MIB.
|
||||||
|
//
|
||||||
|
// Build a MIB with each entry being an array containing the level, type and
|
||||||
|
// a hash that will contain additional entries if the current entry is a node.
|
||||||
|
// We then walk this MIB and create a flattened sysctl name to OID hash.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
goos, goarch string
|
||||||
|
)
|
||||||
|
|
||||||
|
// cmdLine returns this programs's commandline arguments.
|
||||||
|
func cmdLine() string {
|
||||||
|
return "go run mksysctl_openbsd.go " + strings.Join(os.Args[1:], " ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildTags returns build tags.
|
||||||
|
func buildTags() string {
|
||||||
|
return fmt.Sprintf("%s,%s", goarch, goos)
|
||||||
|
}
|
||||||
|
|
||||||
|
// reMatch performs regular expression match and stores the substring slice to value pointed by m.
|
||||||
|
func reMatch(re *regexp.Regexp, str string, m *[]string) bool {
|
||||||
|
*m = re.FindStringSubmatch(str)
|
||||||
|
if *m != nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
type nodeElement struct {
|
||||||
|
n int
|
||||||
|
t string
|
||||||
|
pE *map[string]nodeElement
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
debugEnabled bool
|
||||||
|
mib map[string]nodeElement
|
||||||
|
node *map[string]nodeElement
|
||||||
|
nodeMap map[string]string
|
||||||
|
sysCtl []string
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ctlNames1RE = regexp.MustCompile(`^#define\s+(CTL_NAMES)\s+{`)
|
||||||
|
ctlNames2RE = regexp.MustCompile(`^#define\s+(CTL_(.*)_NAMES)\s+{`)
|
||||||
|
ctlNames3RE = regexp.MustCompile(`^#define\s+((.*)CTL_NAMES)\s+{`)
|
||||||
|
netInetRE = regexp.MustCompile(`^netinet/`)
|
||||||
|
netInet6RE = regexp.MustCompile(`^netinet6/`)
|
||||||
|
netRE = regexp.MustCompile(`^net/`)
|
||||||
|
bracesRE = regexp.MustCompile(`{.*}`)
|
||||||
|
ctlTypeRE = regexp.MustCompile(`{\s+"(\w+)",\s+(CTLTYPE_[A-Z]+)\s+}`)
|
||||||
|
fsNetKernRE = regexp.MustCompile(`^(fs|net|kern)_`)
|
||||||
|
)
|
||||||
|
|
||||||
|
func debug(s string) {
|
||||||
|
if debugEnabled {
|
||||||
|
fmt.Fprintln(os.Stderr, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk the MIB and build a sysctl name to OID mapping.
|
||||||
|
func buildSysctl(pNode *map[string]nodeElement, name string, oid []int) {
|
||||||
|
lNode := pNode // local copy of pointer to node
|
||||||
|
var keys []string
|
||||||
|
for k := range *lNode {
|
||||||
|
keys = append(keys, k)
|
||||||
|
}
|
||||||
|
sort.Strings(keys)
|
||||||
|
|
||||||
|
for _, key := range keys {
|
||||||
|
nodename := name
|
||||||
|
if name != "" {
|
||||||
|
nodename += "."
|
||||||
|
}
|
||||||
|
nodename += key
|
||||||
|
|
||||||
|
nodeoid := append(oid, (*pNode)[key].n)
|
||||||
|
|
||||||
|
if (*pNode)[key].t == `CTLTYPE_NODE` {
|
||||||
|
if _, ok := nodeMap[nodename]; ok {
|
||||||
|
lNode = &mib
|
||||||
|
ctlName := nodeMap[nodename]
|
||||||
|
for _, part := range strings.Split(ctlName, ".") {
|
||||||
|
lNode = ((*lNode)[part]).pE
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lNode = (*pNode)[key].pE
|
||||||
|
}
|
||||||
|
buildSysctl(lNode, nodename, nodeoid)
|
||||||
|
} else if (*pNode)[key].t != "" {
|
||||||
|
oidStr := []string{}
|
||||||
|
for j := range nodeoid {
|
||||||
|
oidStr = append(oidStr, fmt.Sprintf("%d", nodeoid[j]))
|
||||||
|
}
|
||||||
|
text := "\t{ \"" + nodename + "\", []_C_int{ " + strings.Join(oidStr, ", ") + " } }, \n"
|
||||||
|
sysCtl = append(sysCtl, text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Get the OS (using GOOS_TARGET if it exist)
|
||||||
|
goos = os.Getenv("GOOS_TARGET")
|
||||||
|
if goos == "" {
|
||||||
|
goos = os.Getenv("GOOS")
|
||||||
|
}
|
||||||
|
// Get the architecture (using GOARCH_TARGET if it exists)
|
||||||
|
goarch = os.Getenv("GOARCH_TARGET")
|
||||||
|
if goarch == "" {
|
||||||
|
goarch = os.Getenv("GOARCH")
|
||||||
|
}
|
||||||
|
// Check if GOOS and GOARCH environment variables are defined
|
||||||
|
if goarch == "" || goos == "" {
|
||||||
|
fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
mib = make(map[string]nodeElement)
|
||||||
|
headers := [...]string{
|
||||||
|
`sys/sysctl.h`,
|
||||||
|
`sys/socket.h`,
|
||||||
|
`sys/tty.h`,
|
||||||
|
`sys/malloc.h`,
|
||||||
|
`sys/mount.h`,
|
||||||
|
`sys/namei.h`,
|
||||||
|
`sys/sem.h`,
|
||||||
|
`sys/shm.h`,
|
||||||
|
`sys/vmmeter.h`,
|
||||||
|
`uvm/uvmexp.h`,
|
||||||
|
`uvm/uvm_param.h`,
|
||||||
|
`uvm/uvm_swap_encrypt.h`,
|
||||||
|
`ddb/db_var.h`,
|
||||||
|
`net/if.h`,
|
||||||
|
`net/if_pfsync.h`,
|
||||||
|
`net/pipex.h`,
|
||||||
|
`netinet/in.h`,
|
||||||
|
`netinet/icmp_var.h`,
|
||||||
|
`netinet/igmp_var.h`,
|
||||||
|
`netinet/ip_ah.h`,
|
||||||
|
`netinet/ip_carp.h`,
|
||||||
|
`netinet/ip_divert.h`,
|
||||||
|
`netinet/ip_esp.h`,
|
||||||
|
`netinet/ip_ether.h`,
|
||||||
|
`netinet/ip_gre.h`,
|
||||||
|
`netinet/ip_ipcomp.h`,
|
||||||
|
`netinet/ip_ipip.h`,
|
||||||
|
`netinet/pim_var.h`,
|
||||||
|
`netinet/tcp_var.h`,
|
||||||
|
`netinet/udp_var.h`,
|
||||||
|
`netinet6/in6.h`,
|
||||||
|
`netinet6/ip6_divert.h`,
|
||||||
|
`netinet6/pim6_var.h`,
|
||||||
|
`netinet/icmp6.h`,
|
||||||
|
`netmpls/mpls.h`,
|
||||||
|
}
|
||||||
|
|
||||||
|
ctls := [...]string{
|
||||||
|
`kern`,
|
||||||
|
`vm`,
|
||||||
|
`fs`,
|
||||||
|
`net`,
|
||||||
|
//debug /* Special handling required */
|
||||||
|
`hw`,
|
||||||
|
//machdep /* Arch specific */
|
||||||
|
`user`,
|
||||||
|
`ddb`,
|
||||||
|
//vfs /* Special handling required */
|
||||||
|
`fs.posix`,
|
||||||
|
`kern.forkstat`,
|
||||||
|
`kern.intrcnt`,
|
||||||
|
`kern.malloc`,
|
||||||
|
`kern.nchstats`,
|
||||||
|
`kern.seminfo`,
|
||||||
|
`kern.shminfo`,
|
||||||
|
`kern.timecounter`,
|
||||||
|
`kern.tty`,
|
||||||
|
`kern.watchdog`,
|
||||||
|
`net.bpf`,
|
||||||
|
`net.ifq`,
|
||||||
|
`net.inet`,
|
||||||
|
`net.inet.ah`,
|
||||||
|
`net.inet.carp`,
|
||||||
|
`net.inet.divert`,
|
||||||
|
`net.inet.esp`,
|
||||||
|
`net.inet.etherip`,
|
||||||
|
`net.inet.gre`,
|
||||||
|
`net.inet.icmp`,
|
||||||
|
`net.inet.igmp`,
|
||||||
|
`net.inet.ip`,
|
||||||
|
`net.inet.ip.ifq`,
|
||||||
|
`net.inet.ipcomp`,
|
||||||
|
`net.inet.ipip`,
|
||||||
|
`net.inet.mobileip`,
|
||||||
|
`net.inet.pfsync`,
|
||||||
|
`net.inet.pim`,
|
||||||
|
`net.inet.tcp`,
|
||||||
|
`net.inet.udp`,
|
||||||
|
`net.inet6`,
|
||||||
|
`net.inet6.divert`,
|
||||||
|
`net.inet6.ip6`,
|
||||||
|
`net.inet6.icmp6`,
|
||||||
|
`net.inet6.pim6`,
|
||||||
|
`net.inet6.tcp6`,
|
||||||
|
`net.inet6.udp6`,
|
||||||
|
`net.mpls`,
|
||||||
|
`net.mpls.ifq`,
|
||||||
|
`net.key`,
|
||||||
|
`net.pflow`,
|
||||||
|
`net.pfsync`,
|
||||||
|
`net.pipex`,
|
||||||
|
`net.rt`,
|
||||||
|
`vm.swapencrypt`,
|
||||||
|
//vfsgenctl /* Special handling required */
|
||||||
|
}
|
||||||
|
|
||||||
|
// Node name "fixups"
|
||||||
|
ctlMap := map[string]string{
|
||||||
|
"ipproto": "net.inet",
|
||||||
|
"net.inet.ipproto": "net.inet",
|
||||||
|
"net.inet6.ipv6proto": "net.inet6",
|
||||||
|
"net.inet6.ipv6": "net.inet6.ip6",
|
||||||
|
"net.inet.icmpv6": "net.inet6.icmp6",
|
||||||
|
"net.inet6.divert6": "net.inet6.divert",
|
||||||
|
"net.inet6.tcp6": "net.inet.tcp",
|
||||||
|
"net.inet6.udp6": "net.inet.udp",
|
||||||
|
"mpls": "net.mpls",
|
||||||
|
"swpenc": "vm.swapencrypt",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Node mappings
|
||||||
|
nodeMap = map[string]string{
|
||||||
|
"net.inet.ip.ifq": "net.ifq",
|
||||||
|
"net.inet.pfsync": "net.pfsync",
|
||||||
|
"net.mpls.ifq": "net.ifq",
|
||||||
|
}
|
||||||
|
|
||||||
|
mCtls := make(map[string]bool)
|
||||||
|
for _, ctl := range ctls {
|
||||||
|
mCtls[ctl] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, header := range headers {
|
||||||
|
debug("Processing " + header)
|
||||||
|
file, err := os.Open(filepath.Join("/usr/include", header))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
s := bufio.NewScanner(file)
|
||||||
|
for s.Scan() {
|
||||||
|
var sub []string
|
||||||
|
if reMatch(ctlNames1RE, s.Text(), &sub) ||
|
||||||
|
reMatch(ctlNames2RE, s.Text(), &sub) ||
|
||||||
|
reMatch(ctlNames3RE, s.Text(), &sub) {
|
||||||
|
if sub[1] == `CTL_NAMES` {
|
||||||
|
// Top level.
|
||||||
|
node = &mib
|
||||||
|
} else {
|
||||||
|
// Node.
|
||||||
|
nodename := strings.ToLower(sub[2])
|
||||||
|
ctlName := ""
|
||||||
|
if reMatch(netInetRE, header, &sub) {
|
||||||
|
ctlName = "net.inet." + nodename
|
||||||
|
} else if reMatch(netInet6RE, header, &sub) {
|
||||||
|
ctlName = "net.inet6." + nodename
|
||||||
|
} else if reMatch(netRE, header, &sub) {
|
||||||
|
ctlName = "net." + nodename
|
||||||
|
} else {
|
||||||
|
ctlName = nodename
|
||||||
|
ctlName = fsNetKernRE.ReplaceAllString(ctlName, `$1.`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := ctlMap[ctlName]; ok {
|
||||||
|
ctlName = val
|
||||||
|
}
|
||||||
|
if _, ok := mCtls[ctlName]; !ok {
|
||||||
|
debug("Ignoring " + ctlName + "...")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk down from the top of the MIB.
|
||||||
|
node = &mib
|
||||||
|
for _, part := range strings.Split(ctlName, ".") {
|
||||||
|
if _, ok := (*node)[part]; !ok {
|
||||||
|
debug("Missing node " + part)
|
||||||
|
(*node)[part] = nodeElement{n: 0, t: "", pE: &map[string]nodeElement{}}
|
||||||
|
}
|
||||||
|
node = (*node)[part].pE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate current node with entries.
|
||||||
|
i := -1
|
||||||
|
for !strings.HasPrefix(s.Text(), "}") {
|
||||||
|
s.Scan()
|
||||||
|
if reMatch(bracesRE, s.Text(), &sub) {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
if !reMatch(ctlTypeRE, s.Text(), &sub) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
(*node)[sub[1]] = nodeElement{n: i, t: sub[2], pE: &map[string]nodeElement{}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err = s.Err()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
file.Close()
|
||||||
|
}
|
||||||
|
buildSysctl(&mib, "", []int{})
|
||||||
|
|
||||||
|
sort.Strings(sysCtl)
|
||||||
|
text := strings.Join(sysCtl, "")
|
||||||
|
|
||||||
|
fmt.Printf(srcTemplate, cmdLine(), buildTags(), text)
|
||||||
|
}
|
||||||
|
|
||||||
|
const srcTemplate = `// %s
|
||||||
|
// Code generated by the command above; DO NOT EDIT.
|
||||||
|
|
||||||
|
// +build %s
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
type mibentry struct {
|
||||||
|
ctlname string
|
||||||
|
ctloid []_C_int
|
||||||
|
}
|
||||||
|
|
||||||
|
var sysctlMib = []mibentry {
|
||||||
|
%s
|
||||||
|
}
|
||||||
|
`
|
|
@ -1,265 +0,0 @@
|
||||||
#!/usr/bin/env perl
|
|
||||||
|
|
||||||
# Copyright 2011 The Go Authors. All rights reserved.
|
|
||||||
# Use of this source code is governed by a BSD-style
|
|
||||||
# license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
#
|
|
||||||
# Parse the header files for OpenBSD and generate a Go usable sysctl MIB.
|
|
||||||
#
|
|
||||||
# Build a MIB with each entry being an array containing the level, type and
|
|
||||||
# a hash that will contain additional entries if the current entry is a node.
|
|
||||||
# We then walk this MIB and create a flattened sysctl name to OID hash.
|
|
||||||
#
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
if($ENV{'GOARCH'} eq "" || $ENV{'GOOS'} eq "") {
|
|
||||||
print STDERR "GOARCH or GOOS not defined in environment\n";
|
|
||||||
exit 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $debug = 0;
|
|
||||||
my %ctls = ();
|
|
||||||
|
|
||||||
my @headers = qw (
|
|
||||||
sys/sysctl.h
|
|
||||||
sys/socket.h
|
|
||||||
sys/tty.h
|
|
||||||
sys/malloc.h
|
|
||||||
sys/mount.h
|
|
||||||
sys/namei.h
|
|
||||||
sys/sem.h
|
|
||||||
sys/shm.h
|
|
||||||
sys/vmmeter.h
|
|
||||||
uvm/uvmexp.h
|
|
||||||
uvm/uvm_param.h
|
|
||||||
uvm/uvm_swap_encrypt.h
|
|
||||||
ddb/db_var.h
|
|
||||||
net/if.h
|
|
||||||
net/if_pfsync.h
|
|
||||||
net/pipex.h
|
|
||||||
netinet/in.h
|
|
||||||
netinet/icmp_var.h
|
|
||||||
netinet/igmp_var.h
|
|
||||||
netinet/ip_ah.h
|
|
||||||
netinet/ip_carp.h
|
|
||||||
netinet/ip_divert.h
|
|
||||||
netinet/ip_esp.h
|
|
||||||
netinet/ip_ether.h
|
|
||||||
netinet/ip_gre.h
|
|
||||||
netinet/ip_ipcomp.h
|
|
||||||
netinet/ip_ipip.h
|
|
||||||
netinet/pim_var.h
|
|
||||||
netinet/tcp_var.h
|
|
||||||
netinet/udp_var.h
|
|
||||||
netinet6/in6.h
|
|
||||||
netinet6/ip6_divert.h
|
|
||||||
netinet6/pim6_var.h
|
|
||||||
netinet/icmp6.h
|
|
||||||
netmpls/mpls.h
|
|
||||||
);
|
|
||||||
|
|
||||||
my @ctls = qw (
|
|
||||||
kern
|
|
||||||
vm
|
|
||||||
fs
|
|
||||||
net
|
|
||||||
#debug # Special handling required
|
|
||||||
hw
|
|
||||||
#machdep # Arch specific
|
|
||||||
user
|
|
||||||
ddb
|
|
||||||
#vfs # Special handling required
|
|
||||||
fs.posix
|
|
||||||
kern.forkstat
|
|
||||||
kern.intrcnt
|
|
||||||
kern.malloc
|
|
||||||
kern.nchstats
|
|
||||||
kern.seminfo
|
|
||||||
kern.shminfo
|
|
||||||
kern.timecounter
|
|
||||||
kern.tty
|
|
||||||
kern.watchdog
|
|
||||||
net.bpf
|
|
||||||
net.ifq
|
|
||||||
net.inet
|
|
||||||
net.inet.ah
|
|
||||||
net.inet.carp
|
|
||||||
net.inet.divert
|
|
||||||
net.inet.esp
|
|
||||||
net.inet.etherip
|
|
||||||
net.inet.gre
|
|
||||||
net.inet.icmp
|
|
||||||
net.inet.igmp
|
|
||||||
net.inet.ip
|
|
||||||
net.inet.ip.ifq
|
|
||||||
net.inet.ipcomp
|
|
||||||
net.inet.ipip
|
|
||||||
net.inet.mobileip
|
|
||||||
net.inet.pfsync
|
|
||||||
net.inet.pim
|
|
||||||
net.inet.tcp
|
|
||||||
net.inet.udp
|
|
||||||
net.inet6
|
|
||||||
net.inet6.divert
|
|
||||||
net.inet6.ip6
|
|
||||||
net.inet6.icmp6
|
|
||||||
net.inet6.pim6
|
|
||||||
net.inet6.tcp6
|
|
||||||
net.inet6.udp6
|
|
||||||
net.mpls
|
|
||||||
net.mpls.ifq
|
|
||||||
net.key
|
|
||||||
net.pflow
|
|
||||||
net.pfsync
|
|
||||||
net.pipex
|
|
||||||
net.rt
|
|
||||||
vm.swapencrypt
|
|
||||||
#vfsgenctl # Special handling required
|
|
||||||
);
|
|
||||||
|
|
||||||
# Node name "fixups"
|
|
||||||
my %ctl_map = (
|
|
||||||
"ipproto" => "net.inet",
|
|
||||||
"net.inet.ipproto" => "net.inet",
|
|
||||||
"net.inet6.ipv6proto" => "net.inet6",
|
|
||||||
"net.inet6.ipv6" => "net.inet6.ip6",
|
|
||||||
"net.inet.icmpv6" => "net.inet6.icmp6",
|
|
||||||
"net.inet6.divert6" => "net.inet6.divert",
|
|
||||||
"net.inet6.tcp6" => "net.inet.tcp",
|
|
||||||
"net.inet6.udp6" => "net.inet.udp",
|
|
||||||
"mpls" => "net.mpls",
|
|
||||||
"swpenc" => "vm.swapencrypt"
|
|
||||||
);
|
|
||||||
|
|
||||||
# Node mappings
|
|
||||||
my %node_map = (
|
|
||||||
"net.inet.ip.ifq" => "net.ifq",
|
|
||||||
"net.inet.pfsync" => "net.pfsync",
|
|
||||||
"net.mpls.ifq" => "net.ifq"
|
|
||||||
);
|
|
||||||
|
|
||||||
my $ctlname;
|
|
||||||
my %mib = ();
|
|
||||||
my %sysctl = ();
|
|
||||||
my $node;
|
|
||||||
|
|
||||||
sub debug() {
|
|
||||||
print STDERR "$_[0]\n" if $debug;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Walk the MIB and build a sysctl name to OID mapping.
|
|
||||||
sub build_sysctl() {
|
|
||||||
my ($node, $name, $oid) = @_;
|
|
||||||
my %node = %{$node};
|
|
||||||
my @oid = @{$oid};
|
|
||||||
|
|
||||||
foreach my $key (sort keys %node) {
|
|
||||||
my @node = @{$node{$key}};
|
|
||||||
my $nodename = $name.($name ne '' ? '.' : '').$key;
|
|
||||||
my @nodeoid = (@oid, $node[0]);
|
|
||||||
if ($node[1] eq 'CTLTYPE_NODE') {
|
|
||||||
if (exists $node_map{$nodename}) {
|
|
||||||
$node = \%mib;
|
|
||||||
$ctlname = $node_map{$nodename};
|
|
||||||
foreach my $part (split /\./, $ctlname) {
|
|
||||||
$node = \%{@{$$node{$part}}[2]};
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$node = $node[2];
|
|
||||||
}
|
|
||||||
&build_sysctl($node, $nodename, \@nodeoid);
|
|
||||||
} elsif ($node[1] ne '') {
|
|
||||||
$sysctl{$nodename} = \@nodeoid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach my $ctl (@ctls) {
|
|
||||||
$ctls{$ctl} = $ctl;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Build MIB
|
|
||||||
foreach my $header (@headers) {
|
|
||||||
&debug("Processing $header...");
|
|
||||||
open HEADER, "/usr/include/$header" ||
|
|
||||||
print STDERR "Failed to open $header\n";
|
|
||||||
while (<HEADER>) {
|
|
||||||
if ($_ =~ /^#define\s+(CTL_NAMES)\s+{/ ||
|
|
||||||
$_ =~ /^#define\s+(CTL_(.*)_NAMES)\s+{/ ||
|
|
||||||
$_ =~ /^#define\s+((.*)CTL_NAMES)\s+{/) {
|
|
||||||
if ($1 eq 'CTL_NAMES') {
|
|
||||||
# Top level.
|
|
||||||
$node = \%mib;
|
|
||||||
} else {
|
|
||||||
# Node.
|
|
||||||
my $nodename = lc($2);
|
|
||||||
if ($header =~ /^netinet\//) {
|
|
||||||
$ctlname = "net.inet.$nodename";
|
|
||||||
} elsif ($header =~ /^netinet6\//) {
|
|
||||||
$ctlname = "net.inet6.$nodename";
|
|
||||||
} elsif ($header =~ /^net\//) {
|
|
||||||
$ctlname = "net.$nodename";
|
|
||||||
} else {
|
|
||||||
$ctlname = "$nodename";
|
|
||||||
$ctlname =~ s/^(fs|net|kern)_/$1\./;
|
|
||||||
}
|
|
||||||
if (exists $ctl_map{$ctlname}) {
|
|
||||||
$ctlname = $ctl_map{$ctlname};
|
|
||||||
}
|
|
||||||
if (not exists $ctls{$ctlname}) {
|
|
||||||
&debug("Ignoring $ctlname...");
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Walk down from the top of the MIB.
|
|
||||||
$node = \%mib;
|
|
||||||
foreach my $part (split /\./, $ctlname) {
|
|
||||||
if (not exists $$node{$part}) {
|
|
||||||
&debug("Missing node $part");
|
|
||||||
$$node{$part} = [ 0, '', {} ];
|
|
||||||
}
|
|
||||||
$node = \%{@{$$node{$part}}[2]};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Populate current node with entries.
|
|
||||||
my $i = -1;
|
|
||||||
while (defined($_) && $_ !~ /^}/) {
|
|
||||||
$_ = <HEADER>;
|
|
||||||
$i++ if $_ =~ /{.*}/;
|
|
||||||
next if $_ !~ /{\s+"(\w+)",\s+(CTLTYPE_[A-Z]+)\s+}/;
|
|
||||||
$$node{$1} = [ $i, $2, {} ];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close HEADER;
|
|
||||||
}
|
|
||||||
|
|
||||||
&build_sysctl(\%mib, "", []);
|
|
||||||
|
|
||||||
print <<EOF;
|
|
||||||
// mksysctl_openbsd.pl
|
|
||||||
// Code generated by the command above; DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build $ENV{'GOARCH'},$ENV{'GOOS'}
|
|
||||||
|
|
||||||
package unix;
|
|
||||||
|
|
||||||
type mibentry struct {
|
|
||||||
ctlname string
|
|
||||||
ctloid []_C_int
|
|
||||||
}
|
|
||||||
|
|
||||||
var sysctlMib = []mibentry {
|
|
||||||
EOF
|
|
||||||
|
|
||||||
foreach my $name (sort keys %sysctl) {
|
|
||||||
my @oid = @{$sysctl{$name}};
|
|
||||||
print "\t{ \"$name\", []_C_int{ ", join(', ', @oid), " } }, \n";
|
|
||||||
}
|
|
||||||
|
|
||||||
print <<EOF;
|
|
||||||
}
|
|
||||||
EOF
|
|
|
@ -139,7 +139,7 @@ func main() {
|
||||||
text += format(name, num, proto)
|
text += format(name, num, proto)
|
||||||
}
|
}
|
||||||
case "freebsd":
|
case "freebsd":
|
||||||
if t.Match(`^([0-9]+)\s+\S+\s+(?:NO)?STD\s+({ \S+\s+(\w+).*)$`) {
|
if t.Match(`^([0-9]+)\s+\S+\s+(?:(?:NO)?STD|COMPAT10)\s+({ \S+\s+(\w+).*)$`) {
|
||||||
num, proto := t.sub[1], t.sub[2]
|
num, proto := t.sub[1], t.sub[2]
|
||||||
name := fmt.Sprintf("SYS_%s", t.sub[3])
|
name := fmt.Sprintf("SYS_%s", t.sub[3])
|
||||||
text += format(name, num, proto)
|
text += format(name, num, proto)
|
||||||
|
|
|
@ -2,9 +2,6 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build openbsd
|
|
||||||
// +build 386 amd64 arm
|
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
import (
|
import (
|
|
@ -0,0 +1,12 @@
|
||||||
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build aix dragonfly freebsd linux netbsd openbsd
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
// ReadDirent reads directory entries from fd and writes them into buf.
|
||||||
|
func ReadDirent(fd int, buf []byte) (n int, err error) {
|
||||||
|
return Getdents(fd, buf)
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
// ReadDirent reads directory entries from fd and writes them into buf.
|
||||||
|
func ReadDirent(fd int, buf []byte) (n int, err error) {
|
||||||
|
// Final argument is (basep *uintptr) and the syscall doesn't take nil.
|
||||||
|
// 64 bits should be enough. (32 bits isn't even on 386). Since the
|
||||||
|
// actual system call is getdirentries64, 64 is a good guess.
|
||||||
|
// TODO(rsc): Can we use a single global basep for all calls?
|
||||||
|
var base = (*uintptr)(unsafe.Pointer(new(uint64)))
|
||||||
|
return Getdirentries(fd, buf, base)
|
||||||
|
}
|
|
@ -21,10 +21,10 @@ func cmsgAlignOf(salen int) int {
|
||||||
case "aix":
|
case "aix":
|
||||||
// There is no alignment on AIX.
|
// There is no alignment on AIX.
|
||||||
salign = 1
|
salign = 1
|
||||||
case "darwin", "dragonfly", "solaris":
|
case "darwin", "dragonfly", "solaris", "illumos":
|
||||||
// NOTE: It seems like 64-bit Darwin, DragonFly BSD and
|
// NOTE: It seems like 64-bit Darwin, DragonFly BSD,
|
||||||
// Solaris kernels still require 32-bit aligned access to
|
// illumos, and Solaris kernels still require 32-bit
|
||||||
// network subsystem.
|
// aligned access to network subsystem.
|
||||||
if SizeofPtr == 8 {
|
if SizeofPtr == 8 {
|
||||||
salign = 4
|
salign = 4
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,5 +50,4 @@ func BytePtrFromString(s string) (*byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Single-word zero for use when we need a valid pointer to 0 bytes.
|
// Single-word zero for use when we need a valid pointer to 0 bytes.
|
||||||
// See mkunix.pl.
|
|
||||||
var _zero uintptr
|
var _zero uintptr
|
||||||
|
|
|
@ -280,8 +280,24 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
||||||
return -1, ENOSYS
|
return -1, ENOSYS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func direntIno(buf []byte) (uint64, bool) {
|
||||||
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
|
||||||
|
}
|
||||||
|
|
||||||
|
func direntReclen(buf []byte) (uint64, bool) {
|
||||||
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
|
||||||
|
}
|
||||||
|
|
||||||
|
func direntNamlen(buf []byte) (uint64, bool) {
|
||||||
|
reclen, ok := direntReclen(buf)
|
||||||
|
if !ok {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
|
||||||
|
}
|
||||||
|
|
||||||
//sys getdirent(fd int, buf []byte) (n int, err error)
|
//sys getdirent(fd int, buf []byte) (n int, err error)
|
||||||
func ReadDirent(fd int, buf []byte) (n int, err error) {
|
func Getdents(fd int, buf []byte) (n int, err error) {
|
||||||
return getdirent(fd, buf)
|
return getdirent(fd, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,49 +350,12 @@ func (w WaitStatus) Signal() Signal {
|
||||||
|
|
||||||
func (w WaitStatus) Continued() bool { return w&0x01000000 != 0 }
|
func (w WaitStatus) Continued() bool { return w&0x01000000 != 0 }
|
||||||
|
|
||||||
func (w WaitStatus) CoreDump() bool { return w&0x200 != 0 }
|
func (w WaitStatus) CoreDump() bool { return w&0x80 == 0x80 }
|
||||||
|
|
||||||
func (w WaitStatus) TrapCause() int { return -1 }
|
func (w WaitStatus) TrapCause() int { return -1 }
|
||||||
|
|
||||||
//sys ioctl(fd int, req uint, arg uintptr) (err error)
|
//sys ioctl(fd int, req uint, arg uintptr) (err error)
|
||||||
|
|
||||||
// ioctl itself should not be exposed directly, but additional get/set
|
|
||||||
// functions for specific types are permissible.
|
|
||||||
|
|
||||||
// IoctlSetInt performs an ioctl operation which sets an integer value
|
|
||||||
// on fd, using the specified request number.
|
|
||||||
func IoctlSetInt(fd int, req uint, value int) error {
|
|
||||||
return ioctl(fd, req, uintptr(value))
|
|
||||||
}
|
|
||||||
|
|
||||||
func ioctlSetWinsize(fd int, req uint, value *Winsize) error {
|
|
||||||
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func ioctlSetTermios(fd int, req uint, value *Termios) error {
|
|
||||||
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// IoctlGetInt performs an ioctl operation which gets an integer value
|
|
||||||
// from fd, using the specified request number.
|
|
||||||
func IoctlGetInt(fd int, req uint) (int, error) {
|
|
||||||
var value int
|
|
||||||
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
|
||||||
return value, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
|
|
||||||
var value Winsize
|
|
||||||
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
|
||||||
return &value, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
|
|
||||||
var value Termios
|
|
||||||
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
|
||||||
return &value, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// fcntl must never be called with cmd=F_DUP2FD because it doesn't work on AIX
|
// fcntl must never be called with cmd=F_DUP2FD because it doesn't work on AIX
|
||||||
// There is no way to create a custom fcntl and to keep //sys fcntl easily,
|
// There is no way to create a custom fcntl and to keep //sys fcntl easily,
|
||||||
// Therefore, the programmer must call dup2 instead of fcntl in this case.
|
// Therefore, the programmer must call dup2 instead of fcntl in this case.
|
||||||
|
@ -444,8 +423,6 @@ func IoctlGetTermios(fd int, req uint) (*Termios, error) {
|
||||||
//sysnb Times(tms *Tms) (ticks uintptr, err error)
|
//sysnb Times(tms *Tms) (ticks uintptr, err error)
|
||||||
//sysnb Umask(mask int) (oldmask int)
|
//sysnb Umask(mask int) (oldmask int)
|
||||||
//sysnb Uname(buf *Utsname) (err error)
|
//sysnb Uname(buf *Utsname) (err error)
|
||||||
//TODO umount
|
|
||||||
// //sys Unmount(target string, flags int) (err error) = umount
|
|
||||||
//sys Unlink(path string) (err error)
|
//sys Unlink(path string) (err error)
|
||||||
//sys Unlinkat(dirfd int, path string, flags int) (err error)
|
//sys Unlinkat(dirfd int, path string, flags int) (err error)
|
||||||
//sys Ustat(dev int, ubuf *Ustat_t) (err error)
|
//sys Ustat(dev int, ubuf *Ustat_t) (err error)
|
||||||
|
@ -456,8 +433,8 @@ func IoctlGetTermios(fd int, req uint) (*Termios, error) {
|
||||||
//sys Dup2(oldfd int, newfd int) (err error)
|
//sys Dup2(oldfd int, newfd int) (err error)
|
||||||
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = posix_fadvise64
|
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = posix_fadvise64
|
||||||
//sys Fchown(fd int, uid int, gid int) (err error)
|
//sys Fchown(fd int, uid int, gid int) (err error)
|
||||||
//sys Fstat(fd int, stat *Stat_t) (err error)
|
//sys fstat(fd int, stat *Stat_t) (err error)
|
||||||
//sys Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = fstatat
|
//sys fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = fstatat
|
||||||
//sys Fstatfs(fd int, buf *Statfs_t) (err error)
|
//sys Fstatfs(fd int, buf *Statfs_t) (err error)
|
||||||
//sys Ftruncate(fd int, length int64) (err error)
|
//sys Ftruncate(fd int, length int64) (err error)
|
||||||
//sysnb Getegid() (egid int)
|
//sysnb Getegid() (egid int)
|
||||||
|
@ -466,18 +443,17 @@ func IoctlGetTermios(fd int, req uint) (*Termios, error) {
|
||||||
//sysnb Getuid() (uid int)
|
//sysnb Getuid() (uid int)
|
||||||
//sys Lchown(path string, uid int, gid int) (err error)
|
//sys Lchown(path string, uid int, gid int) (err error)
|
||||||
//sys Listen(s int, n int) (err error)
|
//sys Listen(s int, n int) (err error)
|
||||||
//sys Lstat(path string, stat *Stat_t) (err error)
|
//sys lstat(path string, stat *Stat_t) (err error)
|
||||||
//sys Pause() (err error)
|
//sys Pause() (err error)
|
||||||
//sys Pread(fd int, p []byte, offset int64) (n int, err error) = pread64
|
//sys Pread(fd int, p []byte, offset int64) (n int, err error) = pread64
|
||||||
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = pwrite64
|
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = pwrite64
|
||||||
//TODO Select
|
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
|
||||||
// //sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
|
|
||||||
//sys Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error)
|
//sys Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error)
|
||||||
//sysnb Setregid(rgid int, egid int) (err error)
|
//sysnb Setregid(rgid int, egid int) (err error)
|
||||||
//sysnb Setreuid(ruid int, euid int) (err error)
|
//sysnb Setreuid(ruid int, euid int) (err error)
|
||||||
//sys Shutdown(fd int, how int) (err error)
|
//sys Shutdown(fd int, how int) (err error)
|
||||||
//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
|
//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
|
||||||
//sys Stat(path string, stat *Stat_t) (err error)
|
//sys stat(path string, statptr *Stat_t) (err error)
|
||||||
//sys Statfs(path string, buf *Statfs_t) (err error)
|
//sys Statfs(path string, buf *Statfs_t) (err error)
|
||||||
//sys Truncate(path string, length int64) (err error)
|
//sys Truncate(path string, length int64) (err error)
|
||||||
|
|
||||||
|
@ -493,8 +469,10 @@ func IoctlGetTermios(fd int, req uint) (*Termios, error) {
|
||||||
//sysnb getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
|
//sysnb getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
|
||||||
//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)
|
//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)
|
||||||
//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error)
|
//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error)
|
||||||
//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error)
|
|
||||||
//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error)
|
// In order to use msghdr structure with Control, Controllen, nrecvmsg and nsendmsg must be used.
|
||||||
|
//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = nrecvmsg
|
||||||
|
//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = nsendmsg
|
||||||
|
|
||||||
//sys munmap(addr uintptr, length uintptr) (err error)
|
//sys munmap(addr uintptr, length uintptr) (err error)
|
||||||
|
|
||||||
|
@ -547,3 +525,12 @@ func Poll(fds []PollFd, timeout int) (n int, err error) {
|
||||||
//sys Utime(path string, buf *Utimbuf) (err error)
|
//sys Utime(path string, buf *Utimbuf) (err error)
|
||||||
|
|
||||||
//sys Getsystemcfg(label int) (n uint64)
|
//sys Getsystemcfg(label int) (n uint64)
|
||||||
|
|
||||||
|
//sys umount(target string) (err error)
|
||||||
|
func Unmount(target string, flags int) (err error) {
|
||||||
|
if flags != 0 {
|
||||||
|
// AIX doesn't have any flags for umount.
|
||||||
|
return ENOSYS
|
||||||
|
}
|
||||||
|
return umount(target)
|
||||||
|
}
|
||||||
|
|
|
@ -32,3 +32,19 @@ func (msghdr *Msghdr) SetControllen(length int) {
|
||||||
func (cmsg *Cmsghdr) SetLen(length int) {
|
func (cmsg *Cmsghdr) SetLen(length int) {
|
||||||
cmsg.Len = uint32(length)
|
cmsg.Len = uint32(length)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Fstat(fd int, stat *Stat_t) error {
|
||||||
|
return fstat(fd, stat)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Fstatat(dirfd int, path string, stat *Stat_t, flags int) error {
|
||||||
|
return fstatat(dirfd, path, stat, flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Lstat(path string, stat *Stat_t) error {
|
||||||
|
return lstat(path, stat)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Stat(path string, statptr *Stat_t) error {
|
||||||
|
return stat(path, statptr)
|
||||||
|
}
|
||||||
|
|
|
@ -32,3 +32,50 @@ func (msghdr *Msghdr) SetControllen(length int) {
|
||||||
func (cmsg *Cmsghdr) SetLen(length int) {
|
func (cmsg *Cmsghdr) SetLen(length int) {
|
||||||
cmsg.Len = uint32(length)
|
cmsg.Len = uint32(length)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In order to only have Timespec structure, type of Stat_t's fields
|
||||||
|
// Atim, Mtim and Ctim is changed from StTimespec to Timespec during
|
||||||
|
// ztypes generation.
|
||||||
|
// On ppc64, Timespec.Nsec is an int64 while StTimespec.Nsec is an
|
||||||
|
// int32, so the fields' value must be modified.
|
||||||
|
func fixStatTimFields(stat *Stat_t) {
|
||||||
|
stat.Atim.Nsec >>= 32
|
||||||
|
stat.Mtim.Nsec >>= 32
|
||||||
|
stat.Ctim.Nsec >>= 32
|
||||||
|
}
|
||||||
|
|
||||||
|
func Fstat(fd int, stat *Stat_t) error {
|
||||||
|
err := fstat(fd, stat)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fixStatTimFields(stat)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Fstatat(dirfd int, path string, stat *Stat_t, flags int) error {
|
||||||
|
err := fstatat(dirfd, path, stat, flags)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fixStatTimFields(stat)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Lstat(path string, stat *Stat_t) error {
|
||||||
|
err := lstat(path, stat)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fixStatTimFields(stat)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Stat(path string, statptr *Stat_t) error {
|
||||||
|
err := stat(path, statptr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fixStatTimFields(statptr)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -63,15 +63,6 @@ func Setgroups(gids []int) (err error) {
|
||||||
return setgroups(len(a), &a[0])
|
return setgroups(len(a), &a[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadDirent(fd int, buf []byte) (n int, err error) {
|
|
||||||
// Final argument is (basep *uintptr) and the syscall doesn't take nil.
|
|
||||||
// 64 bits should be enough. (32 bits isn't even on 386). Since the
|
|
||||||
// actual system call is getdirentries64, 64 is a good guess.
|
|
||||||
// TODO(rsc): Can we use a single global basep for all calls?
|
|
||||||
var base = (*uintptr)(unsafe.Pointer(new(uint64)))
|
|
||||||
return Getdirentries(fd, buf, base)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait status is 7 bits at bottom, either 0 (exited),
|
// Wait status is 7 bits at bottom, either 0 (exited),
|
||||||
// 0x7F (stopped), or a signal number that caused an exit.
|
// 0x7F (stopped), or a signal number that caused an exit.
|
||||||
// The 0x80 bit is whether there was a core dump.
|
// The 0x80 bit is whether there was a core dump.
|
||||||
|
@ -86,6 +77,7 @@ const (
|
||||||
shift = 8
|
shift = 8
|
||||||
|
|
||||||
exited = 0
|
exited = 0
|
||||||
|
killed = 9
|
||||||
stopped = 0x7F
|
stopped = 0x7F
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -112,6 +104,8 @@ func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
|
||||||
|
|
||||||
func (w WaitStatus) Stopped() bool { return w&mask == stopped && syscall.Signal(w>>shift) != SIGSTOP }
|
func (w WaitStatus) Stopped() bool { return w&mask == stopped && syscall.Signal(w>>shift) != SIGSTOP }
|
||||||
|
|
||||||
|
func (w WaitStatus) Killed() bool { return w&mask == killed && syscall.Signal(w>>shift) != SIGKILL }
|
||||||
|
|
||||||
func (w WaitStatus) Continued() bool { return w&mask == stopped && syscall.Signal(w>>shift) == SIGSTOP }
|
func (w WaitStatus) Continued() bool { return w&mask == stopped && syscall.Signal(w>>shift) == SIGSTOP }
|
||||||
|
|
||||||
func (w WaitStatus) StopSignal() syscall.Signal {
|
func (w WaitStatus) StopSignal() syscall.Signal {
|
||||||
|
|
|
@ -77,7 +77,18 @@ func nametomib(name string) (mib []_C_int, err error) {
|
||||||
return buf[0 : n/siz], nil
|
return buf[0 : n/siz], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error)
|
func direntIno(buf []byte) (uint64, bool) {
|
||||||
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
|
||||||
|
}
|
||||||
|
|
||||||
|
func direntReclen(buf []byte) (uint64, bool) {
|
||||||
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
|
||||||
|
}
|
||||||
|
|
||||||
|
func direntNamlen(buf []byte) (uint64, bool) {
|
||||||
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
|
||||||
|
}
|
||||||
|
|
||||||
func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) }
|
func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) }
|
||||||
func PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) }
|
func PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) }
|
||||||
|
|
||||||
|
@ -328,43 +339,6 @@ func Kill(pid int, signum syscall.Signal) (err error) { return kill(pid, int(sig
|
||||||
|
|
||||||
//sys ioctl(fd int, req uint, arg uintptr) (err error)
|
//sys ioctl(fd int, req uint, arg uintptr) (err error)
|
||||||
|
|
||||||
// ioctl itself should not be exposed directly, but additional get/set
|
|
||||||
// functions for specific types are permissible.
|
|
||||||
|
|
||||||
// IoctlSetInt performs an ioctl operation which sets an integer value
|
|
||||||
// on fd, using the specified request number.
|
|
||||||
func IoctlSetInt(fd int, req uint, value int) error {
|
|
||||||
return ioctl(fd, req, uintptr(value))
|
|
||||||
}
|
|
||||||
|
|
||||||
func ioctlSetWinsize(fd int, req uint, value *Winsize) error {
|
|
||||||
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func ioctlSetTermios(fd int, req uint, value *Termios) error {
|
|
||||||
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// IoctlGetInt performs an ioctl operation which gets an integer value
|
|
||||||
// from fd, using the specified request number.
|
|
||||||
func IoctlGetInt(fd int, req uint) (int, error) {
|
|
||||||
var value int
|
|
||||||
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
|
||||||
return value, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
|
|
||||||
var value Winsize
|
|
||||||
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
|
||||||
return &value, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
|
|
||||||
var value Termios
|
|
||||||
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
|
||||||
return &value, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func Uname(uname *Utsname) error {
|
func Uname(uname *Utsname) error {
|
||||||
mib := []_C_int{CTL_KERN, KERN_OSTYPE}
|
mib := []_C_int{CTL_KERN, KERN_OSTYPE}
|
||||||
n := unsafe.Sizeof(uname.Sysname)
|
n := unsafe.Sizeof(uname.Sysname)
|
||||||
|
|
|
@ -10,6 +10,8 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error)
|
||||||
|
|
||||||
func setTimespec(sec, nsec int64) Timespec {
|
func setTimespec(sec, nsec int64) Timespec {
|
||||||
return Timespec{Sec: int32(sec), Nsec: int32(nsec)}
|
return Timespec{Sec: int32(sec), Nsec: int32(nsec)}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,8 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error)
|
||||||
|
|
||||||
func setTimespec(sec, nsec int64) Timespec {
|
func setTimespec(sec, nsec int64) Timespec {
|
||||||
return Timespec{Sec: sec, Nsec: nsec}
|
return Timespec{Sec: sec, Nsec: nsec}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,10 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func ptrace(request int, pid int, addr uintptr, data uintptr) error {
|
||||||
|
return ENOTSUP
|
||||||
|
}
|
||||||
|
|
||||||
func setTimespec(sec, nsec int64) Timespec {
|
func setTimespec(sec, nsec int64) Timespec {
|
||||||
return Timespec{Sec: int32(sec), Nsec: int32(nsec)}
|
return Timespec{Sec: int32(sec), Nsec: int32(nsec)}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,10 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func ptrace(request int, pid int, addr uintptr, data uintptr) error {
|
||||||
|
return ENOTSUP
|
||||||
|
}
|
||||||
|
|
||||||
func setTimespec(sec, nsec int64) Timespec {
|
func setTimespec(sec, nsec int64) Timespec {
|
||||||
return Timespec{Sec: sec, Nsec: nsec}
|
return Timespec{Sec: sec, Nsec: nsec}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,22 @@ func nametomib(name string) (mib []_C_int, err error) {
|
||||||
return buf[0 : n/siz], nil
|
return buf[0 : n/siz], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func direntIno(buf []byte) (uint64, bool) {
|
||||||
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Fileno), unsafe.Sizeof(Dirent{}.Fileno))
|
||||||
|
}
|
||||||
|
|
||||||
|
func direntReclen(buf []byte) (uint64, bool) {
|
||||||
|
namlen, ok := direntNamlen(buf)
|
||||||
|
if !ok {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
return (16 + namlen + 1 + 7) &^ 7, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func direntNamlen(buf []byte) (uint64, bool) {
|
||||||
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
|
||||||
|
}
|
||||||
|
|
||||||
//sysnb pipe() (r int, w int, err error)
|
//sysnb pipe() (r int, w int, err error)
|
||||||
|
|
||||||
func Pipe(p []int) (err error) {
|
func Pipe(p []int) (err error) {
|
||||||
|
@ -134,43 +150,6 @@ func setattrlistTimes(path string, times []Timespec, flags int) error {
|
||||||
|
|
||||||
//sys ioctl(fd int, req uint, arg uintptr) (err error)
|
//sys ioctl(fd int, req uint, arg uintptr) (err error)
|
||||||
|
|
||||||
// ioctl itself should not be exposed directly, but additional get/set
|
|
||||||
// functions for specific types are permissible.
|
|
||||||
|
|
||||||
// IoctlSetInt performs an ioctl operation which sets an integer value
|
|
||||||
// on fd, using the specified request number.
|
|
||||||
func IoctlSetInt(fd int, req uint, value int) error {
|
|
||||||
return ioctl(fd, req, uintptr(value))
|
|
||||||
}
|
|
||||||
|
|
||||||
func ioctlSetWinsize(fd int, req uint, value *Winsize) error {
|
|
||||||
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func ioctlSetTermios(fd int, req uint, value *Termios) error {
|
|
||||||
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// IoctlGetInt performs an ioctl operation which gets an integer value
|
|
||||||
// from fd, using the specified request number.
|
|
||||||
func IoctlGetInt(fd int, req uint) (int, error) {
|
|
||||||
var value int
|
|
||||||
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
|
||||||
return value, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
|
|
||||||
var value Winsize
|
|
||||||
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
|
||||||
return &value, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
|
|
||||||
var value Termios
|
|
||||||
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
|
||||||
return &value, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func sysctlUname(mib []_C_int, old *byte, oldlen *uintptr) error {
|
func sysctlUname(mib []_C_int, old *byte, oldlen *uintptr) error {
|
||||||
err := sysctl(mib, old, oldlen, nil, 0)
|
err := sysctl(mib, old, oldlen, nil, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -269,6 +248,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
||||||
//sys Fstatfs(fd int, stat *Statfs_t) (err error)
|
//sys Fstatfs(fd int, stat *Statfs_t) (err error)
|
||||||
//sys Fsync(fd int) (err error)
|
//sys Fsync(fd int) (err error)
|
||||||
//sys Ftruncate(fd int, length int64) (err error)
|
//sys Ftruncate(fd int, length int64) (err error)
|
||||||
|
//sys Getdents(fd int, buf []byte) (n int, err error)
|
||||||
//sys Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error)
|
//sys Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error)
|
||||||
//sys Getdtablesize() (size int)
|
//sys Getdtablesize() (size int)
|
||||||
//sysnb Getegid() (egid int)
|
//sysnb Getegid() (egid int)
|
||||||
|
|
|
@ -82,6 +82,18 @@ func nametomib(name string) (mib []_C_int, err error) {
|
||||||
return buf[0 : n/siz], nil
|
return buf[0 : n/siz], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func direntIno(buf []byte) (uint64, bool) {
|
||||||
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Fileno), unsafe.Sizeof(Dirent{}.Fileno))
|
||||||
|
}
|
||||||
|
|
||||||
|
func direntReclen(buf []byte) (uint64, bool) {
|
||||||
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
|
||||||
|
}
|
||||||
|
|
||||||
|
func direntNamlen(buf []byte) (uint64, bool) {
|
||||||
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
|
||||||
|
}
|
||||||
|
|
||||||
func Pipe(p []int) (err error) {
|
func Pipe(p []int) (err error) {
|
||||||
return Pipe2(p, 0)
|
return Pipe2(p, 0)
|
||||||
}
|
}
|
||||||
|
@ -189,43 +201,6 @@ func setattrlistTimes(path string, times []Timespec, flags int) error {
|
||||||
|
|
||||||
//sys ioctl(fd int, req uint, arg uintptr) (err error)
|
//sys ioctl(fd int, req uint, arg uintptr) (err error)
|
||||||
|
|
||||||
// ioctl itself should not be exposed directly, but additional get/set
|
|
||||||
// functions for specific types are permissible.
|
|
||||||
|
|
||||||
// IoctlSetInt performs an ioctl operation which sets an integer value
|
|
||||||
// on fd, using the specified request number.
|
|
||||||
func IoctlSetInt(fd int, req uint, value int) error {
|
|
||||||
return ioctl(fd, req, uintptr(value))
|
|
||||||
}
|
|
||||||
|
|
||||||
func ioctlSetWinsize(fd int, req uint, value *Winsize) error {
|
|
||||||
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func ioctlSetTermios(fd int, req uint, value *Termios) error {
|
|
||||||
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// IoctlGetInt performs an ioctl operation which gets an integer value
|
|
||||||
// from fd, using the specified request number.
|
|
||||||
func IoctlGetInt(fd int, req uint) (int, error) {
|
|
||||||
var value int
|
|
||||||
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
|
||||||
return value, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
|
|
||||||
var value Winsize
|
|
||||||
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
|
||||||
return &value, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
|
|
||||||
var value Termios
|
|
||||||
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
|
||||||
return &value, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func Uname(uname *Utsname) error {
|
func Uname(uname *Utsname) error {
|
||||||
mib := []_C_int{CTL_KERN, KERN_OSTYPE}
|
mib := []_C_int{CTL_KERN, KERN_OSTYPE}
|
||||||
n := unsafe.Sizeof(uname.Sysname)
|
n := unsafe.Sizeof(uname.Sysname)
|
||||||
|
@ -362,7 +337,21 @@ func Getdents(fd int, buf []byte) (n int, err error) {
|
||||||
|
|
||||||
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
|
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
|
||||||
if supportsABI(_ino64First) {
|
if supportsABI(_ino64First) {
|
||||||
return getdirentries_freebsd12(fd, buf, basep)
|
if basep == nil || unsafe.Sizeof(*basep) == 8 {
|
||||||
|
return getdirentries_freebsd12(fd, buf, (*uint64)(unsafe.Pointer(basep)))
|
||||||
|
}
|
||||||
|
// The freebsd12 syscall needs a 64-bit base. On 32-bit machines
|
||||||
|
// we can't just use the basep passed in. See #32498.
|
||||||
|
var base uint64 = uint64(*basep)
|
||||||
|
n, err = getdirentries_freebsd12(fd, buf, &base)
|
||||||
|
*basep = uintptr(base)
|
||||||
|
if base>>32 != 0 {
|
||||||
|
// We can't stuff the base back into a uintptr, so any
|
||||||
|
// future calls would be suspect. Generate an error.
|
||||||
|
// EIO is allowed by getdirentries.
|
||||||
|
err = EIO
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// The old syscall entries are smaller than the new. Use 1/4 of the original
|
// The old syscall entries are smaller than the new. Use 1/4 of the original
|
||||||
|
@ -404,22 +393,22 @@ func roundup(x, y int) int {
|
||||||
|
|
||||||
func (s *Stat_t) convertFrom(old *stat_freebsd11_t) {
|
func (s *Stat_t) convertFrom(old *stat_freebsd11_t) {
|
||||||
*s = Stat_t{
|
*s = Stat_t{
|
||||||
Dev: uint64(old.Dev),
|
Dev: uint64(old.Dev),
|
||||||
Ino: uint64(old.Ino),
|
Ino: uint64(old.Ino),
|
||||||
Nlink: uint64(old.Nlink),
|
Nlink: uint64(old.Nlink),
|
||||||
Mode: old.Mode,
|
Mode: old.Mode,
|
||||||
Uid: old.Uid,
|
Uid: old.Uid,
|
||||||
Gid: old.Gid,
|
Gid: old.Gid,
|
||||||
Rdev: uint64(old.Rdev),
|
Rdev: uint64(old.Rdev),
|
||||||
Atim: old.Atim,
|
Atim: old.Atim,
|
||||||
Mtim: old.Mtim,
|
Mtim: old.Mtim,
|
||||||
Ctim: old.Ctim,
|
Ctim: old.Ctim,
|
||||||
Birthtim: old.Birthtim,
|
Btim: old.Btim,
|
||||||
Size: old.Size,
|
Size: old.Size,
|
||||||
Blocks: old.Blocks,
|
Blocks: old.Blocks,
|
||||||
Blksize: old.Blksize,
|
Blksize: old.Blksize,
|
||||||
Flags: old.Flags,
|
Flags: old.Flags,
|
||||||
Gen: uint64(old.Gen),
|
Gen: uint64(old.Gen),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -507,6 +496,70 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
||||||
return sendfile(outfd, infd, offset, count)
|
return sendfile(outfd, infd, offset, count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//sys ptrace(request int, pid int, addr uintptr, data int) (err error)
|
||||||
|
|
||||||
|
func PtraceAttach(pid int) (err error) {
|
||||||
|
return ptrace(PTRACE_ATTACH, pid, 0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PtraceCont(pid int, signal int) (err error) {
|
||||||
|
return ptrace(PTRACE_CONT, pid, 1, signal)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PtraceDetach(pid int) (err error) {
|
||||||
|
return ptrace(PTRACE_DETACH, pid, 1, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PtraceGetFpRegs(pid int, fpregsout *FpReg) (err error) {
|
||||||
|
return ptrace(PTRACE_GETFPREGS, pid, uintptr(unsafe.Pointer(fpregsout)), 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PtraceGetFsBase(pid int, fsbase *int64) (err error) {
|
||||||
|
return ptrace(PTRACE_GETFSBASE, pid, uintptr(unsafe.Pointer(fsbase)), 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PtraceGetRegs(pid int, regsout *Reg) (err error) {
|
||||||
|
return ptrace(PTRACE_GETREGS, pid, uintptr(unsafe.Pointer(regsout)), 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
|
||||||
|
ioDesc := PtraceIoDesc{Op: int32(req), Offs: (*byte)(unsafe.Pointer(addr)), Addr: (*byte)(unsafe.Pointer(&out[0])), Len: uint(countin)}
|
||||||
|
err = ptrace(PTRACE_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
||||||
|
return int(ioDesc.Len), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func PtraceLwpEvents(pid int, enable int) (err error) {
|
||||||
|
return ptrace(PTRACE_LWPEVENTS, pid, 0, enable)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PtraceLwpInfo(pid int, info uintptr) (err error) {
|
||||||
|
return ptrace(PTRACE_LWPINFO, pid, info, int(unsafe.Sizeof(PtraceLwpInfoStruct{})))
|
||||||
|
}
|
||||||
|
|
||||||
|
func PtracePeekData(pid int, addr uintptr, out []byte) (count int, err error) {
|
||||||
|
return PtraceIO(PIOD_READ_D, pid, addr, out, SizeofLong)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PtracePeekText(pid int, addr uintptr, out []byte) (count int, err error) {
|
||||||
|
return PtraceIO(PIOD_READ_I, pid, addr, out, SizeofLong)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PtracePokeData(pid int, addr uintptr, data []byte) (count int, err error) {
|
||||||
|
return PtraceIO(PIOD_WRITE_D, pid, addr, data, SizeofLong)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PtracePokeText(pid int, addr uintptr, data []byte) (count int, err error) {
|
||||||
|
return PtraceIO(PIOD_WRITE_I, pid, addr, data, SizeofLong)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PtraceSetRegs(pid int, regs *Reg) (err error) {
|
||||||
|
return ptrace(PTRACE_SETREGS, pid, uintptr(unsafe.Pointer(regs)), 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PtraceSingleStep(pid int) (err error) {
|
||||||
|
return ptrace(PTRACE_SINGLESTEP, pid, 1, 0)
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exposed directly
|
* Exposed directly
|
||||||
*/
|
*/
|
||||||
|
@ -555,7 +608,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
||||||
//sys Fsync(fd int) (err error)
|
//sys Fsync(fd int) (err error)
|
||||||
//sys Ftruncate(fd int, length int64) (err error)
|
//sys Ftruncate(fd int, length int64) (err error)
|
||||||
//sys getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error)
|
//sys getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error)
|
||||||
//sys getdirentries_freebsd12(fd int, buf []byte, basep *uintptr) (n int, err error)
|
//sys getdirentries_freebsd12(fd int, buf []byte, basep *uint64) (n int, err error)
|
||||||
//sys Getdtablesize() (size int)
|
//sys Getdtablesize() (size int)
|
||||||
//sysnb Getegid() (egid int)
|
//sysnb Getegid() (egid int)
|
||||||
//sysnb Geteuid() (uid int)
|
//sysnb Geteuid() (uid int)
|
||||||
|
|
|
@ -13,7 +13,6 @@ package unix
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"net"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
@ -72,6 +71,17 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
|
||||||
// ioctl itself should not be exposed directly, but additional get/set
|
// ioctl itself should not be exposed directly, but additional get/set
|
||||||
// functions for specific types are permissible.
|
// functions for specific types are permissible.
|
||||||
|
|
||||||
|
// IoctlRetInt performs an ioctl operation specified by req on a device
|
||||||
|
// associated with opened file descriptor fd, and returns a non-negative
|
||||||
|
// integer that is returned by the ioctl syscall.
|
||||||
|
func IoctlRetInt(fd int, req uint) (int, error) {
|
||||||
|
ret, _, err := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), 0)
|
||||||
|
if err != 0 {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return int(ret), nil
|
||||||
|
}
|
||||||
|
|
||||||
// IoctlSetPointerInt performs an ioctl operation which sets an
|
// IoctlSetPointerInt performs an ioctl operation which sets an
|
||||||
// integer value on fd, using the specified request number. The ioctl
|
// integer value on fd, using the specified request number. The ioctl
|
||||||
// argument is called with a pointer to the integer value, rather than
|
// argument is called with a pointer to the integer value, rather than
|
||||||
|
@ -81,46 +91,18 @@ func IoctlSetPointerInt(fd int, req uint, value int) error {
|
||||||
return ioctl(fd, req, uintptr(unsafe.Pointer(&v)))
|
return ioctl(fd, req, uintptr(unsafe.Pointer(&v)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// IoctlSetInt performs an ioctl operation which sets an integer value
|
|
||||||
// on fd, using the specified request number.
|
|
||||||
func IoctlSetInt(fd int, req uint, value int) error {
|
|
||||||
return ioctl(fd, req, uintptr(value))
|
|
||||||
}
|
|
||||||
|
|
||||||
func ioctlSetWinsize(fd int, req uint, value *Winsize) error {
|
|
||||||
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func ioctlSetTermios(fd int, req uint, value *Termios) error {
|
|
||||||
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func IoctlSetRTCTime(fd int, value *RTCTime) error {
|
func IoctlSetRTCTime(fd int, value *RTCTime) error {
|
||||||
err := ioctl(fd, RTC_SET_TIME, uintptr(unsafe.Pointer(value)))
|
err := ioctl(fd, RTC_SET_TIME, uintptr(unsafe.Pointer(value)))
|
||||||
runtime.KeepAlive(value)
|
runtime.KeepAlive(value)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// IoctlGetInt performs an ioctl operation which gets an integer value
|
func IoctlGetUint32(fd int, req uint) (uint32, error) {
|
||||||
// from fd, using the specified request number.
|
var value uint32
|
||||||
func IoctlGetInt(fd int, req uint) (int, error) {
|
|
||||||
var value int
|
|
||||||
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
||||||
return value, err
|
return value, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
|
|
||||||
var value Winsize
|
|
||||||
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
|
||||||
return &value, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
|
|
||||||
var value Termios
|
|
||||||
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
|
||||||
return &value, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func IoctlGetRTCTime(fd int) (*RTCTime, error) {
|
func IoctlGetRTCTime(fd int) (*RTCTime, error) {
|
||||||
var value RTCTime
|
var value RTCTime
|
||||||
err := ioctl(fd, RTC_RD_TIME, uintptr(unsafe.Pointer(&value)))
|
err := ioctl(fd, RTC_RD_TIME, uintptr(unsafe.Pointer(&value)))
|
||||||
|
@ -759,7 +741,7 @@ const px_proto_oe = 0
|
||||||
|
|
||||||
type SockaddrPPPoE struct {
|
type SockaddrPPPoE struct {
|
||||||
SID uint16
|
SID uint16
|
||||||
Remote net.HardwareAddr
|
Remote []byte
|
||||||
Dev string
|
Dev string
|
||||||
raw RawSockaddrPPPoX
|
raw RawSockaddrPPPoX
|
||||||
}
|
}
|
||||||
|
@ -910,7 +892,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
||||||
}
|
}
|
||||||
sa := &SockaddrPPPoE{
|
sa := &SockaddrPPPoE{
|
||||||
SID: binary.BigEndian.Uint16(pp[6:8]),
|
SID: binary.BigEndian.Uint16(pp[6:8]),
|
||||||
Remote: net.HardwareAddr(pp[8:14]),
|
Remote: pp[8:14],
|
||||||
}
|
}
|
||||||
for i := 14; i < 14+IFNAMSIZ; i++ {
|
for i := 14; i < 14+IFNAMSIZ; i++ {
|
||||||
if pp[i] == 0 {
|
if pp[i] == 0 {
|
||||||
|
@ -1408,8 +1390,20 @@ func Reboot(cmd int) (err error) {
|
||||||
return reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, "")
|
return reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadDirent(fd int, buf []byte) (n int, err error) {
|
func direntIno(buf []byte) (uint64, bool) {
|
||||||
return Getdents(fd, buf)
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
|
||||||
|
}
|
||||||
|
|
||||||
|
func direntReclen(buf []byte) (uint64, bool) {
|
||||||
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
|
||||||
|
}
|
||||||
|
|
||||||
|
func direntNamlen(buf []byte) (uint64, bool) {
|
||||||
|
reclen, ok := direntReclen(buf)
|
||||||
|
if !ok {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys mount(source string, target string, fstype string, flags uintptr, data *byte) (err error)
|
//sys mount(source string, target string, fstype string, flags uintptr, data *byte) (err error)
|
||||||
|
@ -1444,6 +1438,8 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
||||||
//sys Acct(path string) (err error)
|
//sys Acct(path string) (err error)
|
||||||
//sys AddKey(keyType string, description string, payload []byte, ringid int) (id int, err error)
|
//sys AddKey(keyType string, description string, payload []byte, ringid int) (id int, err error)
|
||||||
//sys Adjtimex(buf *Timex) (state int, err error)
|
//sys Adjtimex(buf *Timex) (state int, err error)
|
||||||
|
//sys Capget(hdr *CapUserHeader, data *CapUserData) (err error)
|
||||||
|
//sys Capset(hdr *CapUserHeader, data *CapUserData) (err error)
|
||||||
//sys Chdir(path string) (err error)
|
//sys Chdir(path string) (err error)
|
||||||
//sys Chroot(path string) (err error)
|
//sys Chroot(path string) (err error)
|
||||||
//sys ClockGetres(clockid int32, res *Timespec) (err error)
|
//sys ClockGetres(clockid int32, res *Timespec) (err error)
|
||||||
|
@ -1531,9 +1527,13 @@ func Setgid(uid int) (err error) {
|
||||||
return EOPNOTSUPP
|
return EOPNOTSUPP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Signalfd(fd int, sigmask *Sigset_t, flags int) (newfd int, err error) {
|
||||||
|
return signalfd(fd, sigmask, _C__NSIG/8, flags)
|
||||||
|
}
|
||||||
|
|
||||||
//sys Setpriority(which int, who int, prio int) (err error)
|
//sys Setpriority(which int, who int, prio int) (err error)
|
||||||
//sys Setxattr(path string, attr string, data []byte, flags int) (err error)
|
//sys Setxattr(path string, attr string, data []byte, flags int) (err error)
|
||||||
//sys Signalfd(fd int, mask *Sigset_t, flags int) = SYS_SIGNALFD4
|
//sys signalfd(fd int, sigmask *Sigset_t, maskSize uintptr, flags int) (newfd int, err error) = SYS_SIGNALFD4
|
||||||
//sys Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error)
|
//sys Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error)
|
||||||
//sys Sync()
|
//sys Sync()
|
||||||
//sys Syncfs(fd int) (err error)
|
//sys Syncfs(fd int) (err error)
|
||||||
|
@ -1662,6 +1662,82 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
|
||||||
return EACCES
|
return EACCES
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//sys nameToHandleAt(dirFD int, pathname string, fh *fileHandle, mountID *_C_int, flags int) (err error) = SYS_NAME_TO_HANDLE_AT
|
||||||
|
//sys openByHandleAt(mountFD int, fh *fileHandle, flags int) (fd int, err error) = SYS_OPEN_BY_HANDLE_AT
|
||||||
|
|
||||||
|
// fileHandle is the argument to nameToHandleAt and openByHandleAt. We
|
||||||
|
// originally tried to generate it via unix/linux/types.go with "type
|
||||||
|
// fileHandle C.struct_file_handle" but that generated empty structs
|
||||||
|
// for mips64 and mips64le. Instead, hard code it for now (it's the
|
||||||
|
// same everywhere else) until the mips64 generator issue is fixed.
|
||||||
|
type fileHandle struct {
|
||||||
|
Bytes uint32
|
||||||
|
Type int32
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileHandle represents the C struct file_handle used by
|
||||||
|
// name_to_handle_at (see NameToHandleAt) and open_by_handle_at (see
|
||||||
|
// OpenByHandleAt).
|
||||||
|
type FileHandle struct {
|
||||||
|
*fileHandle
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFileHandle constructs a FileHandle.
|
||||||
|
func NewFileHandle(handleType int32, handle []byte) FileHandle {
|
||||||
|
const hdrSize = unsafe.Sizeof(fileHandle{})
|
||||||
|
buf := make([]byte, hdrSize+uintptr(len(handle)))
|
||||||
|
copy(buf[hdrSize:], handle)
|
||||||
|
fh := (*fileHandle)(unsafe.Pointer(&buf[0]))
|
||||||
|
fh.Type = handleType
|
||||||
|
fh.Bytes = uint32(len(handle))
|
||||||
|
return FileHandle{fh}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fh *FileHandle) Size() int { return int(fh.fileHandle.Bytes) }
|
||||||
|
func (fh *FileHandle) Type() int32 { return fh.fileHandle.Type }
|
||||||
|
func (fh *FileHandle) Bytes() []byte {
|
||||||
|
n := fh.Size()
|
||||||
|
if n == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return (*[1 << 30]byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&fh.fileHandle.Type)) + 4))[:n:n]
|
||||||
|
}
|
||||||
|
|
||||||
|
// NameToHandleAt wraps the name_to_handle_at system call; it obtains
|
||||||
|
// a handle for a path name.
|
||||||
|
func NameToHandleAt(dirfd int, path string, flags int) (handle FileHandle, mountID int, err error) {
|
||||||
|
var mid _C_int
|
||||||
|
// Try first with a small buffer, assuming the handle will
|
||||||
|
// only be 32 bytes.
|
||||||
|
size := uint32(32 + unsafe.Sizeof(fileHandle{}))
|
||||||
|
didResize := false
|
||||||
|
for {
|
||||||
|
buf := make([]byte, size)
|
||||||
|
fh := (*fileHandle)(unsafe.Pointer(&buf[0]))
|
||||||
|
fh.Bytes = size - uint32(unsafe.Sizeof(fileHandle{}))
|
||||||
|
err = nameToHandleAt(dirfd, path, fh, &mid, flags)
|
||||||
|
if err == EOVERFLOW {
|
||||||
|
if didResize {
|
||||||
|
// We shouldn't need to resize more than once
|
||||||
|
return
|
||||||
|
}
|
||||||
|
didResize = true
|
||||||
|
size = fh.Bytes + uint32(unsafe.Sizeof(fileHandle{}))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return FileHandle{fh}, int(mid), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenByHandleAt wraps the open_by_handle_at system call; it opens a
|
||||||
|
// file via a handle as previously returned by NameToHandleAt.
|
||||||
|
func OpenByHandleAt(mountFD int, handle FileHandle, flags int) (fd int, err error) {
|
||||||
|
return openByHandleAt(mountFD, handle.fileHandle, flags)
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unimplemented
|
* Unimplemented
|
||||||
*/
|
*/
|
||||||
|
@ -1669,8 +1745,6 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
|
||||||
// Alarm
|
// Alarm
|
||||||
// ArchPrctl
|
// ArchPrctl
|
||||||
// Brk
|
// Brk
|
||||||
// Capget
|
|
||||||
// Capset
|
|
||||||
// ClockNanosleep
|
// ClockNanosleep
|
||||||
// ClockSettime
|
// ClockSettime
|
||||||
// Clone
|
// Clone
|
||||||
|
|
|
@ -272,3 +272,16 @@ func SyncFileRange(fd int, off int64, n int64, flags int) error {
|
||||||
// order of their arguments.
|
// order of their arguments.
|
||||||
return armSyncFileRange(fd, flags, off, n)
|
return armSyncFileRange(fd, flags, off, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//sys kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error)
|
||||||
|
|
||||||
|
func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error {
|
||||||
|
cmdlineLen := len(cmdline)
|
||||||
|
if cmdlineLen > 0 {
|
||||||
|
// Account for the additional NULL byte added by
|
||||||
|
// BytePtrFromString in kexecFileLoad. The kexec_file_load
|
||||||
|
// syscall expects a NULL-terminated string.
|
||||||
|
cmdlineLen++
|
||||||
|
}
|
||||||
|
return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags)
|
||||||
|
}
|
||||||
|
|
|
@ -94,6 +94,18 @@ func nametomib(name string) (mib []_C_int, err error) {
|
||||||
return mib, nil
|
return mib, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func direntIno(buf []byte) (uint64, bool) {
|
||||||
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Fileno), unsafe.Sizeof(Dirent{}.Fileno))
|
||||||
|
}
|
||||||
|
|
||||||
|
func direntReclen(buf []byte) (uint64, bool) {
|
||||||
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
|
||||||
|
}
|
||||||
|
|
||||||
|
func direntNamlen(buf []byte) (uint64, bool) {
|
||||||
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
|
||||||
|
}
|
||||||
|
|
||||||
func SysctlClockinfo(name string) (*Clockinfo, error) {
|
func SysctlClockinfo(name string) (*Clockinfo, error) {
|
||||||
mib, err := sysctlmib(name)
|
mib, err := sysctlmib(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -120,9 +132,30 @@ func Pipe(p []int) (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys getdents(fd int, buf []byte) (n int, err error)
|
//sys Getdents(fd int, buf []byte) (n int, err error)
|
||||||
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
|
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
|
||||||
return getdents(fd, buf)
|
n, err = Getdents(fd, buf)
|
||||||
|
if err != nil || basep == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var off int64
|
||||||
|
off, err = Seek(fd, 0, 1 /* SEEK_CUR */)
|
||||||
|
if err != nil {
|
||||||
|
*basep = ^uintptr(0)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
*basep = uintptr(off)
|
||||||
|
if unsafe.Sizeof(*basep) == 8 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if off>>32 != 0 {
|
||||||
|
// We can't stuff the offset back into a uintptr, so any
|
||||||
|
// future calls would be suspect. Generate an error.
|
||||||
|
// EIO is allowed by getdirentries.
|
||||||
|
err = EIO
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const ImplementsGetwd = true
|
const ImplementsGetwd = true
|
||||||
|
@ -154,43 +187,6 @@ func setattrlistTimes(path string, times []Timespec, flags int) error {
|
||||||
|
|
||||||
//sys ioctl(fd int, req uint, arg uintptr) (err error)
|
//sys ioctl(fd int, req uint, arg uintptr) (err error)
|
||||||
|
|
||||||
// ioctl itself should not be exposed directly, but additional get/set
|
|
||||||
// functions for specific types are permissible.
|
|
||||||
|
|
||||||
// IoctlSetInt performs an ioctl operation which sets an integer value
|
|
||||||
// on fd, using the specified request number.
|
|
||||||
func IoctlSetInt(fd int, req uint, value int) error {
|
|
||||||
return ioctl(fd, req, uintptr(value))
|
|
||||||
}
|
|
||||||
|
|
||||||
func ioctlSetWinsize(fd int, req uint, value *Winsize) error {
|
|
||||||
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func ioctlSetTermios(fd int, req uint, value *Termios) error {
|
|
||||||
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// IoctlGetInt performs an ioctl operation which gets an integer value
|
|
||||||
// from fd, using the specified request number.
|
|
||||||
func IoctlGetInt(fd int, req uint) (int, error) {
|
|
||||||
var value int
|
|
||||||
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
|
||||||
return value, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
|
|
||||||
var value Winsize
|
|
||||||
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
|
||||||
return &value, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
|
|
||||||
var value Termios
|
|
||||||
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
|
||||||
return &value, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func IoctlGetPtmget(fd int, req uint) (*Ptmget, error) {
|
func IoctlGetPtmget(fd int, req uint) (*Ptmget, error) {
|
||||||
var value Ptmget
|
var value Ptmget
|
||||||
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
||||||
|
|
|
@ -43,6 +43,18 @@ func nametomib(name string) (mib []_C_int, err error) {
|
||||||
return nil, EINVAL
|
return nil, EINVAL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func direntIno(buf []byte) (uint64, bool) {
|
||||||
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Fileno), unsafe.Sizeof(Dirent{}.Fileno))
|
||||||
|
}
|
||||||
|
|
||||||
|
func direntReclen(buf []byte) (uint64, bool) {
|
||||||
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
|
||||||
|
}
|
||||||
|
|
||||||
|
func direntNamlen(buf []byte) (uint64, bool) {
|
||||||
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
|
||||||
|
}
|
||||||
|
|
||||||
func SysctlClockinfo(name string) (*Clockinfo, error) {
|
func SysctlClockinfo(name string) (*Clockinfo, error) {
|
||||||
mib, err := sysctlmib(name)
|
mib, err := sysctlmib(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -89,9 +101,30 @@ func Pipe(p []int) (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys getdents(fd int, buf []byte) (n int, err error)
|
//sys Getdents(fd int, buf []byte) (n int, err error)
|
||||||
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
|
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
|
||||||
return getdents(fd, buf)
|
n, err = Getdents(fd, buf)
|
||||||
|
if err != nil || basep == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var off int64
|
||||||
|
off, err = Seek(fd, 0, 1 /* SEEK_CUR */)
|
||||||
|
if err != nil {
|
||||||
|
*basep = ^uintptr(0)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
*basep = uintptr(off)
|
||||||
|
if unsafe.Sizeof(*basep) == 8 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if off>>32 != 0 {
|
||||||
|
// We can't stuff the offset back into a uintptr, so any
|
||||||
|
// future calls would be suspect. Generate an error.
|
||||||
|
// EIO was allowed by getdirentries.
|
||||||
|
err = EIO
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const ImplementsGetwd = true
|
const ImplementsGetwd = true
|
||||||
|
@ -145,43 +178,6 @@ func setattrlistTimes(path string, times []Timespec, flags int) error {
|
||||||
|
|
||||||
//sys ioctl(fd int, req uint, arg uintptr) (err error)
|
//sys ioctl(fd int, req uint, arg uintptr) (err error)
|
||||||
|
|
||||||
// ioctl itself should not be exposed directly, but additional get/set
|
|
||||||
// functions for specific types are permissible.
|
|
||||||
|
|
||||||
// IoctlSetInt performs an ioctl operation which sets an integer value
|
|
||||||
// on fd, using the specified request number.
|
|
||||||
func IoctlSetInt(fd int, req uint, value int) error {
|
|
||||||
return ioctl(fd, req, uintptr(value))
|
|
||||||
}
|
|
||||||
|
|
||||||
func ioctlSetWinsize(fd int, req uint, value *Winsize) error {
|
|
||||||
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func ioctlSetTermios(fd int, req uint, value *Termios) error {
|
|
||||||
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// IoctlGetInt performs an ioctl operation which gets an integer value
|
|
||||||
// from fd, using the specified request number.
|
|
||||||
func IoctlGetInt(fd int, req uint) (int, error) {
|
|
||||||
var value int
|
|
||||||
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
|
||||||
return value, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
|
|
||||||
var value Winsize
|
|
||||||
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
|
||||||
return &value, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
|
|
||||||
var value Termios
|
|
||||||
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
|
||||||
return &value, err
|
|
||||||
}
|
|
||||||
|
|
||||||
//sys ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error)
|
//sys ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error)
|
||||||
|
|
||||||
func Ppoll(fds []PollFd, timeout *Timespec, sigmask *Sigset_t) (n int, err error) {
|
func Ppoll(fds []PollFd, timeout *Timespec, sigmask *Sigset_t) (n int, err error) {
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build arm64,openbsd
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
func setTimespec(sec, nsec int64) Timespec {
|
||||||
|
return Timespec{Sec: sec, Nsec: nsec}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setTimeval(sec, usec int64) Timeval {
|
||||||
|
return Timeval{Sec: sec, Usec: usec}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetKevent(k *Kevent_t, fd, mode, flags int) {
|
||||||
|
k.Ident = uint64(fd)
|
||||||
|
k.Filter = int16(mode)
|
||||||
|
k.Flags = uint16(flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (iov *Iovec) SetLen(length int) {
|
||||||
|
iov.Len = uint64(length)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msghdr *Msghdr) SetControllen(length int) {
|
||||||
|
msghdr.Controllen = uint32(length)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmsg *Cmsghdr) SetLen(length int) {
|
||||||
|
cmsg.Len = uint32(length)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SYS___SYSCTL is used by syscall_bsd.go for all BSDs, but in modern versions
|
||||||
|
// of openbsd/amd64 the syscall is called sysctl instead of __sysctl.
|
||||||
|
const SYS___SYSCTL = SYS_SYSCTL
|
|
@ -35,6 +35,22 @@ type SockaddrDatalink struct {
|
||||||
raw RawSockaddrDatalink
|
raw RawSockaddrDatalink
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func direntIno(buf []byte) (uint64, bool) {
|
||||||
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
|
||||||
|
}
|
||||||
|
|
||||||
|
func direntReclen(buf []byte) (uint64, bool) {
|
||||||
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
|
||||||
|
}
|
||||||
|
|
||||||
|
func direntNamlen(buf []byte) (uint64, bool) {
|
||||||
|
reclen, ok := direntReclen(buf)
|
||||||
|
if !ok {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
|
||||||
|
}
|
||||||
|
|
||||||
//sysnb pipe(p *[2]_C_int) (n int, err error)
|
//sysnb pipe(p *[2]_C_int) (n int, err error)
|
||||||
|
|
||||||
func Pipe(p []int) (err error) {
|
func Pipe(p []int) (err error) {
|
||||||
|
@ -189,6 +205,7 @@ func Setgroups(gids []int) (err error) {
|
||||||
return setgroups(len(a), &a[0])
|
return setgroups(len(a), &a[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadDirent reads directory entries from fd and writes them into buf.
|
||||||
func ReadDirent(fd int, buf []byte) (n int, err error) {
|
func ReadDirent(fd int, buf []byte) (n int, err error) {
|
||||||
// Final argument is (basep *uintptr) and the syscall doesn't take nil.
|
// Final argument is (basep *uintptr) and the syscall doesn't take nil.
|
||||||
// TODO(rsc): Can we use a single global basep for all calls?
|
// TODO(rsc): Can we use a single global basep for all calls?
|
||||||
|
@ -536,40 +553,10 @@ func Minor(dev uint64) uint32 {
|
||||||
|
|
||||||
//sys ioctl(fd int, req uint, arg uintptr) (err error)
|
//sys ioctl(fd int, req uint, arg uintptr) (err error)
|
||||||
|
|
||||||
func IoctlSetInt(fd int, req uint, value int) (err error) {
|
|
||||||
return ioctl(fd, req, uintptr(value))
|
|
||||||
}
|
|
||||||
|
|
||||||
func ioctlSetWinsize(fd int, req uint, value *Winsize) (err error) {
|
|
||||||
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func ioctlSetTermios(fd int, req uint, value *Termios) (err error) {
|
|
||||||
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func IoctlSetTermio(fd int, req uint, value *Termio) (err error) {
|
func IoctlSetTermio(fd int, req uint, value *Termio) (err error) {
|
||||||
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func IoctlGetInt(fd int, req uint) (int, error) {
|
|
||||||
var value int
|
|
||||||
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
|
||||||
return value, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
|
|
||||||
var value Winsize
|
|
||||||
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
|
||||||
return &value, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
|
|
||||||
var value Termios
|
|
||||||
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
|
||||||
return &value, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func IoctlGetTermio(fd int, req uint) (*Termio, error) {
|
func IoctlGetTermio(fd int, req uint) (*Termio, error) {
|
||||||
var value Termio
|
var value Termio
|
||||||
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue