pin down grpc and related library in go.mod (#2222)

* pin down grpc and related library in go.mod

Signed-off-by: galal-hussein <hussein.galal.ahmed.11@gmail.com>

* go mod tidy

Signed-off-by: galal-hussein <hussein.galal.ahmed.11@gmail.com>
This commit is contained in:
Hussein Galal 2020-09-10 00:08:21 +02:00 committed by GitHub
parent cc8cc1a58b
commit 041f18f6da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
423 changed files with 89736 additions and 35556 deletions

6
go.mod
View File

@ -24,8 +24,12 @@ replace (
github.com/matryer/moq => github.com/rancher/moq v0.0.0-20190404221404-ee5226d43009 github.com/matryer/moq => github.com/rancher/moq v0.0.0-20190404221404-ee5226d43009
github.com/opencontainers/runc => github.com/opencontainers/runc v1.0.0-rc92 github.com/opencontainers/runc => github.com/opencontainers/runc v1.0.0-rc92
github.com/opencontainers/runtime-spec => github.com/opencontainers/runtime-spec v1.0.3-0.20200728170252-4d89ac9fbff6 github.com/opencontainers/runtime-spec => github.com/opencontainers/runtime-spec v1.0.3-0.20200728170252-4d89ac9fbff6
go.etcd.io/etcd => go.etcd.io/etcd v0.5.0-alpha.5.0.20200824191128-ae9734ed278b
golang.org/x/crypto => golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2
golang.org/x/net => golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7
golang.org/x/sys => golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456
google.golang.org/genproto => google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63 google.golang.org/genproto => google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63
google.golang.org/grpc => google.golang.org/grpc v1.27.1 google.golang.org/grpc => google.golang.org/grpc v1.26.0
gopkg.in/square/go-jose.v2 => gopkg.in/square/go-jose.v2 v2.2.2 gopkg.in/square/go-jose.v2 => gopkg.in/square/go-jose.v2 v2.2.2
k8s.io/api => github.com/rancher/kubernetes/staging/src/k8s.io/api v1.19.1-k3s1 k8s.io/api => github.com/rancher/kubernetes/staging/src/k8s.io/api v1.19.1-k3s1
k8s.io/apiextensions-apiserver => github.com/rancher/kubernetes/staging/src/k8s.io/apiextensions-apiserver v1.19.1-k3s1 k8s.io/apiextensions-apiserver => github.com/rancher/kubernetes/staging/src/k8s.io/apiextensions-apiserver v1.19.1-k3s1

105
go.sum
View File

@ -849,9 +849,8 @@ go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0=
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.etcd.io/etcd v0.5.0-alpha.5.0.20200824191128-ae9734ed278b h1:3kC4J3eQF6p1UEfQTkC67eEeb3rTk+shQqdX6tFyq9Q=
go.etcd.io/etcd v0.5.0-alpha.5.0.20200819165624-17cef6e3e9d5 h1:Gqga3zA9tdAcfqobUGjSoCob5L3f8Dt5EuOp3ihNZko= go.etcd.io/etcd v0.5.0-alpha.5.0.20200824191128-ae9734ed278b/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg=
go.etcd.io/etcd v0.5.0-alpha.5.0.20200819165624-17cef6e3e9d5/go.mod h1:skWido08r9w6Lq/w70DO5XYIKMu4QFu1+4VsqLQuJy8=
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.2 h1:jxcFYjlkl8xaERsgLo+RNquI0epW6zuy/ZRQs6jnrFA= go.mongodb.org/mongo-driver v1.1.2 h1:jxcFYjlkl8xaERsgLo+RNquI0epW6zuy/ZRQs6jnrFA=
@ -867,22 +866,8 @@ go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/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-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@ -909,38 +894,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190328230028-74de082e2cca/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/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/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -954,54 +909,8 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 h1:ng0gs1AKnRRuEMZoTLLlbOd+C17zUDepwGQBb/n+JVg=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/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-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4 h1:5/PjkGUjvEU5Gl6BxmvKRPpqo2uNMv4rcHBMwzk/st8=
golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1 h1:sIky/MyNRSHTrdxfsiUSS4WIAMvInbeXljJz+jDjeYE=
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6 h1:DvY3Zkh7KabQE/kfzMvYvKirSiguP9Q/veMtkYyf0o8=
golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
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=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -1071,8 +980,8 @@ google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpC
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63 h1:YzfoEYWbODU5Fbt37+h7X16BWQbad7Q4S6gclTKFXM8= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63 h1:YzfoEYWbODU5Fbt37+h7X16BWQbad7Q4S6gclTKFXM8=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk= google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=

View File

@ -49,7 +49,7 @@ func TouchDirAll(dir string) error {
if Exist(dir) { if Exist(dir) {
err := CheckDirPermission(dir, PrivateDirMode) err := CheckDirPermission(dir, PrivateDirMode)
if err != nil { if err != nil {
return err plog.Warningf("check file permission: %v", err)
} }
} else { } else {
err := os.MkdirAll(dir, PrivateDirMode) err := os.MkdirAll(dir, PrivateDirMode)
@ -122,7 +122,7 @@ func CheckDirPermission(dir string, perm os.FileMode) error {
} }
dirMode := dirInfo.Mode().Perm() dirMode := dirInfo.Mode().Perm()
if dirMode != perm { if dirMode != perm {
err = fmt.Errorf("directory %q,%q exist without desired file permission %q.", dir, dirInfo.Mode(), os.FileMode(PrivateDirMode)) err = fmt.Errorf("directory %q exist, but the permission is %q. The recommended permission is %q to prevent possible unprivileged access to the data.", dir, dirInfo.Mode(), os.FileMode(PrivateDirMode))
return err return err
} }
return nil return nil

View File

@ -26,7 +26,7 @@ import (
var ( var (
// MinClusterVersion is the min cluster version this etcd binary is compatible with. // MinClusterVersion is the min cluster version this etcd binary is compatible with.
MinClusterVersion = "3.0.0" MinClusterVersion = "3.0.0"
Version = "3.4.12" Version = "3.4.13"
APIVersion = "unknown" APIVersion = "unknown"
// Git SHA Value will be set during build // Git SHA Value will be set during build

View File

@ -1,16 +0,0 @@
// 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 go1.11,!gccgo,!purego
package chacha20
const bufSize = 256
//go:noescape
func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32)
func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) {
xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter)
}

View File

@ -1,398 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package chacha20 implements the ChaCha20 and XChaCha20 encryption algorithms
// as specified in RFC 8439 and draft-irtf-cfrg-xchacha-01.
package chacha20
import (
"crypto/cipher"
"encoding/binary"
"errors"
"math/bits"
"golang.org/x/crypto/internal/subtle"
)
const (
// KeySize is the size of the key used by this cipher, in bytes.
KeySize = 32
// NonceSize is the size of the nonce used with the standard variant of this
// cipher, in bytes.
//
// Note that this is too short to be safely generated at random if the same
// key is reused more than 2³² times.
NonceSize = 12
// NonceSizeX is the size of the nonce used with the XChaCha20 variant of
// this cipher, in bytes.
NonceSizeX = 24
)
// Cipher is a stateful instance of ChaCha20 or XChaCha20 using a particular key
// and nonce. A *Cipher implements the cipher.Stream interface.
type Cipher struct {
// The ChaCha20 state is 16 words: 4 constant, 8 of key, 1 of counter
// (incremented after each block), and 3 of nonce.
key [8]uint32
counter uint32
nonce [3]uint32
// The last len bytes of buf are leftover key stream bytes from the previous
// XORKeyStream invocation. The size of buf depends on how many blocks are
// computed at a time by xorKeyStreamBlocks.
buf [bufSize]byte
len int
// overflow is set when the counter overflowed, no more blocks can be
// generated, and the next XORKeyStream call should panic.
overflow bool
// The counter-independent results of the first round are cached after they
// are computed the first time.
precompDone bool
p1, p5, p9, p13 uint32
p2, p6, p10, p14 uint32
p3, p7, p11, p15 uint32
}
var _ cipher.Stream = (*Cipher)(nil)
// NewUnauthenticatedCipher creates a new ChaCha20 stream cipher with the given
// 32 bytes key and a 12 or 24 bytes nonce. If a nonce of 24 bytes is provided,
// the XChaCha20 construction will be used. It returns an error if key or nonce
// have any other length.
//
// Note that ChaCha20, like all stream ciphers, is not authenticated and allows
// attackers to silently tamper with the plaintext. For this reason, it is more
// appropriate as a building block than as a standalone encryption mechanism.
// Instead, consider using package golang.org/x/crypto/chacha20poly1305.
func NewUnauthenticatedCipher(key, nonce []byte) (*Cipher, error) {
// This function is split into a wrapper so that the Cipher allocation will
// be inlined, and depending on how the caller uses the return value, won't
// escape to the heap.
c := &Cipher{}
return newUnauthenticatedCipher(c, key, nonce)
}
func newUnauthenticatedCipher(c *Cipher, key, nonce []byte) (*Cipher, error) {
if len(key) != KeySize {
return nil, errors.New("chacha20: wrong key size")
}
if len(nonce) == NonceSizeX {
// XChaCha20 uses the ChaCha20 core to mix 16 bytes of the nonce into a
// derived key, allowing it to operate on a nonce of 24 bytes. See
// draft-irtf-cfrg-xchacha-01, Section 2.3.
key, _ = HChaCha20(key, nonce[0:16])
cNonce := make([]byte, NonceSize)
copy(cNonce[4:12], nonce[16:24])
nonce = cNonce
} else if len(nonce) != NonceSize {
return nil, errors.New("chacha20: wrong nonce size")
}
key, nonce = key[:KeySize], nonce[:NonceSize] // bounds check elimination hint
c.key = [8]uint32{
binary.LittleEndian.Uint32(key[0:4]),
binary.LittleEndian.Uint32(key[4:8]),
binary.LittleEndian.Uint32(key[8:12]),
binary.LittleEndian.Uint32(key[12:16]),
binary.LittleEndian.Uint32(key[16:20]),
binary.LittleEndian.Uint32(key[20:24]),
binary.LittleEndian.Uint32(key[24:28]),
binary.LittleEndian.Uint32(key[28:32]),
}
c.nonce = [3]uint32{
binary.LittleEndian.Uint32(nonce[0:4]),
binary.LittleEndian.Uint32(nonce[4:8]),
binary.LittleEndian.Uint32(nonce[8:12]),
}
return c, nil
}
// The constant first 4 words of the ChaCha20 state.
const (
j0 uint32 = 0x61707865 // expa
j1 uint32 = 0x3320646e // nd 3
j2 uint32 = 0x79622d32 // 2-by
j3 uint32 = 0x6b206574 // te k
)
const blockSize = 64
// quarterRound is the core of ChaCha20. It shuffles the bits of 4 state words.
// It's executed 4 times for each of the 20 ChaCha20 rounds, operating on all 16
// words each round, in columnar or diagonal groups of 4 at a time.
func quarterRound(a, b, c, d uint32) (uint32, uint32, uint32, uint32) {
a += b
d ^= a
d = bits.RotateLeft32(d, 16)
c += d
b ^= c
b = bits.RotateLeft32(b, 12)
a += b
d ^= a
d = bits.RotateLeft32(d, 8)
c += d
b ^= c
b = bits.RotateLeft32(b, 7)
return a, b, c, d
}
// SetCounter sets the Cipher counter. The next invocation of XORKeyStream will
// behave as if (64 * counter) bytes had been encrypted so far.
//
// To prevent accidental counter reuse, SetCounter panics if counter is less
// than the current value.
//
// Note that the execution time of XORKeyStream is not independent of the
// counter value.
func (s *Cipher) SetCounter(counter uint32) {
// Internally, s may buffer multiple blocks, which complicates this
// implementation slightly. When checking whether the counter has rolled
// back, we must use both s.counter and s.len to determine how many blocks
// we have already output.
outputCounter := s.counter - uint32(s.len)/blockSize
if s.overflow || counter < outputCounter {
panic("chacha20: SetCounter attempted to rollback counter")
}
// In the general case, we set the new counter value and reset s.len to 0,
// causing the next call to XORKeyStream to refill the buffer. However, if
// we're advancing within the existing buffer, we can save work by simply
// setting s.len.
if counter < s.counter {
s.len = int(s.counter-counter) * blockSize
} else {
s.counter = counter
s.len = 0
}
}
// XORKeyStream XORs each byte in the given slice with a byte from the
// cipher's key stream. Dst and src must overlap entirely or not at all.
//
// If len(dst) < len(src), XORKeyStream will panic. It is acceptable
// to pass a dst bigger than src, and in that case, XORKeyStream will
// only update dst[:len(src)] and will not touch the rest of dst.
//
// Multiple calls to XORKeyStream behave as if the concatenation of
// the src buffers was passed in a single run. That is, Cipher
// maintains state and does not reset at each XORKeyStream call.
func (s *Cipher) XORKeyStream(dst, src []byte) {
if len(src) == 0 {
return
}
if len(dst) < len(src) {
panic("chacha20: output smaller than input")
}
dst = dst[:len(src)]
if subtle.InexactOverlap(dst, src) {
panic("chacha20: invalid buffer overlap")
}
// First, drain any remaining key stream from a previous XORKeyStream.
if s.len != 0 {
keyStream := s.buf[bufSize-s.len:]
if len(src) < len(keyStream) {
keyStream = keyStream[:len(src)]
}
_ = src[len(keyStream)-1] // bounds check elimination hint
for i, b := range keyStream {
dst[i] = src[i] ^ b
}
s.len -= len(keyStream)
dst, src = dst[len(keyStream):], src[len(keyStream):]
}
if len(src) == 0 {
return
}
// If we'd need to let the counter overflow and keep generating output,
// panic immediately. If instead we'd only reach the last block, remember
// not to generate any more output after the buffer is drained.
numBlocks := (uint64(len(src)) + blockSize - 1) / blockSize
if s.overflow || uint64(s.counter)+numBlocks > 1<<32 {
panic("chacha20: counter overflow")
} else if uint64(s.counter)+numBlocks == 1<<32 {
s.overflow = true
}
// xorKeyStreamBlocks implementations expect input lengths that are a
// multiple of bufSize. Platform-specific ones process multiple blocks at a
// time, so have bufSizes that are a multiple of blockSize.
full := len(src) - len(src)%bufSize
if full > 0 {
s.xorKeyStreamBlocks(dst[:full], src[:full])
}
dst, src = dst[full:], src[full:]
// If using a multi-block xorKeyStreamBlocks would overflow, use the generic
// one that does one block at a time.
const blocksPerBuf = bufSize / blockSize
if uint64(s.counter)+blocksPerBuf > 1<<32 {
s.buf = [bufSize]byte{}
numBlocks := (len(src) + blockSize - 1) / blockSize
buf := s.buf[bufSize-numBlocks*blockSize:]
copy(buf, src)
s.xorKeyStreamBlocksGeneric(buf, buf)
s.len = len(buf) - copy(dst, buf)
return
}
// If we have a partial (multi-)block, pad it for xorKeyStreamBlocks, and
// keep the leftover keystream for the next XORKeyStream invocation.
if len(src) > 0 {
s.buf = [bufSize]byte{}
copy(s.buf[:], src)
s.xorKeyStreamBlocks(s.buf[:], s.buf[:])
s.len = bufSize - copy(dst, s.buf[:])
}
}
func (s *Cipher) xorKeyStreamBlocksGeneric(dst, src []byte) {
if len(dst) != len(src) || len(dst)%blockSize != 0 {
panic("chacha20: internal error: wrong dst and/or src length")
}
// To generate each block of key stream, the initial cipher state
// (represented below) is passed through 20 rounds of shuffling,
// alternatively applying quarterRounds by columns (like 1, 5, 9, 13)
// or by diagonals (like 1, 6, 11, 12).
//
// 0:cccccccc 1:cccccccc 2:cccccccc 3:cccccccc
// 4:kkkkkkkk 5:kkkkkkkk 6:kkkkkkkk 7:kkkkkkkk
// 8:kkkkkkkk 9:kkkkkkkk 10:kkkkkkkk 11:kkkkkkkk
// 12:bbbbbbbb 13:nnnnnnnn 14:nnnnnnnn 15:nnnnnnnn
//
// c=constant k=key b=blockcount n=nonce
var (
c0, c1, c2, c3 = j0, j1, j2, j3
c4, c5, c6, c7 = s.key[0], s.key[1], s.key[2], s.key[3]
c8, c9, c10, c11 = s.key[4], s.key[5], s.key[6], s.key[7]
_, c13, c14, c15 = s.counter, s.nonce[0], s.nonce[1], s.nonce[2]
)
// Three quarters of the first round don't depend on the counter, so we can
// calculate them here, and reuse them for multiple blocks in the loop, and
// for future XORKeyStream invocations.
if !s.precompDone {
s.p1, s.p5, s.p9, s.p13 = quarterRound(c1, c5, c9, c13)
s.p2, s.p6, s.p10, s.p14 = quarterRound(c2, c6, c10, c14)
s.p3, s.p7, s.p11, s.p15 = quarterRound(c3, c7, c11, c15)
s.precompDone = true
}
// A condition of len(src) > 0 would be sufficient, but this also
// acts as a bounds check elimination hint.
for len(src) >= 64 && len(dst) >= 64 {
// The remainder of the first column round.
fcr0, fcr4, fcr8, fcr12 := quarterRound(c0, c4, c8, s.counter)
// The second diagonal round.
x0, x5, x10, x15 := quarterRound(fcr0, s.p5, s.p10, s.p15)
x1, x6, x11, x12 := quarterRound(s.p1, s.p6, s.p11, fcr12)
x2, x7, x8, x13 := quarterRound(s.p2, s.p7, fcr8, s.p13)
x3, x4, x9, x14 := quarterRound(s.p3, fcr4, s.p9, s.p14)
// The remaining 18 rounds.
for i := 0; i < 9; i++ {
// Column round.
x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12)
x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13)
x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14)
x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15)
// Diagonal round.
x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15)
x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12)
x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13)
x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14)
}
// Add back the initial state to generate the key stream, then
// XOR the key stream with the source and write out the result.
addXor(dst[0:4], src[0:4], x0, c0)
addXor(dst[4:8], src[4:8], x1, c1)
addXor(dst[8:12], src[8:12], x2, c2)
addXor(dst[12:16], src[12:16], x3, c3)
addXor(dst[16:20], src[16:20], x4, c4)
addXor(dst[20:24], src[20:24], x5, c5)
addXor(dst[24:28], src[24:28], x6, c6)
addXor(dst[28:32], src[28:32], x7, c7)
addXor(dst[32:36], src[32:36], x8, c8)
addXor(dst[36:40], src[36:40], x9, c9)
addXor(dst[40:44], src[40:44], x10, c10)
addXor(dst[44:48], src[44:48], x11, c11)
addXor(dst[48:52], src[48:52], x12, s.counter)
addXor(dst[52:56], src[52:56], x13, c13)
addXor(dst[56:60], src[56:60], x14, c14)
addXor(dst[60:64], src[60:64], x15, c15)
s.counter += 1
src, dst = src[blockSize:], dst[blockSize:]
}
}
// HChaCha20 uses the ChaCha20 core to generate a derived key from a 32 bytes
// key and a 16 bytes nonce. It returns an error if key or nonce have any other
// length. It is used as part of the XChaCha20 construction.
func HChaCha20(key, nonce []byte) ([]byte, error) {
// This function is split into a wrapper so that the slice allocation will
// be inlined, and depending on how the caller uses the return value, won't
// escape to the heap.
out := make([]byte, 32)
return hChaCha20(out, key, nonce)
}
func hChaCha20(out, key, nonce []byte) ([]byte, error) {
if len(key) != KeySize {
return nil, errors.New("chacha20: wrong HChaCha20 key size")
}
if len(nonce) != 16 {
return nil, errors.New("chacha20: wrong HChaCha20 nonce size")
}
x0, x1, x2, x3 := j0, j1, j2, j3
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])
for i := 0; i < 10; i++ {
// Diagonal round.
x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12)
x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13)
x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14)
x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15)
// Column round.
x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15)
x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12)
x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13)
x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14)
}
_ = out[31] // bounds check elimination hint
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 out, nil
}

View File

@ -1,16 +0,0 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !gccgo,!purego
package chacha20
const bufSize = 256
//go:noescape
func chaCha20_ctr32_vsx(out, inp *byte, len int, key *[8]uint32, counter *uint32)
func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) {
chaCha20_ctr32_vsx(&dst[0], &src[0], len(src), &c.key, &c.counter)
}

View File

@ -1,449 +0,0 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Based on CRYPTOGAMS code with the following comment:
// # ====================================================================
// # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
// # project. The module is, however, dual licensed under OpenSSL and
// # CRYPTOGAMS licenses depending on where you obtain it. For further
// # details see http://www.openssl.org/~appro/cryptogams/.
// # ====================================================================
// Code for the perl script that generates the ppc64 assembler
// can be found in the cryptogams repository at the link below. It is based on
// the original from openssl.
// https://github.com/dot-asm/cryptogams/commit/a60f5b50ed908e91
// The differences in this and the original implementation are
// due to the calling conventions and initialization of constants.
// +build !gccgo,!purego
#include "textflag.h"
#define OUT R3
#define INP R4
#define LEN R5
#define KEY R6
#define CNT R7
#define TMP R15
#define CONSTBASE R16
#define BLOCKS R17
DATA consts<>+0x00(SB)/8, $0x3320646e61707865
DATA consts<>+0x08(SB)/8, $0x6b20657479622d32
DATA consts<>+0x10(SB)/8, $0x0000000000000001
DATA consts<>+0x18(SB)/8, $0x0000000000000000
DATA consts<>+0x20(SB)/8, $0x0000000000000004
DATA consts<>+0x28(SB)/8, $0x0000000000000000
DATA consts<>+0x30(SB)/8, $0x0a0b08090e0f0c0d
DATA consts<>+0x38(SB)/8, $0x0203000106070405
DATA consts<>+0x40(SB)/8, $0x090a0b080d0e0f0c
DATA consts<>+0x48(SB)/8, $0x0102030005060704
DATA consts<>+0x50(SB)/8, $0x6170786561707865
DATA consts<>+0x58(SB)/8, $0x6170786561707865
DATA consts<>+0x60(SB)/8, $0x3320646e3320646e
DATA consts<>+0x68(SB)/8, $0x3320646e3320646e
DATA consts<>+0x70(SB)/8, $0x79622d3279622d32
DATA consts<>+0x78(SB)/8, $0x79622d3279622d32
DATA consts<>+0x80(SB)/8, $0x6b2065746b206574
DATA consts<>+0x88(SB)/8, $0x6b2065746b206574
DATA consts<>+0x90(SB)/8, $0x0000000100000000
DATA consts<>+0x98(SB)/8, $0x0000000300000002
GLOBL consts<>(SB), RODATA, $0xa0
//func chaCha20_ctr32_vsx(out, inp *byte, len int, key *[8]uint32, counter *uint32)
TEXT ·chaCha20_ctr32_vsx(SB),NOSPLIT,$64-40
MOVD out+0(FP), OUT
MOVD inp+8(FP), INP
MOVD len+16(FP), LEN
MOVD key+24(FP), KEY
MOVD counter+32(FP), CNT
// Addressing for constants
MOVD $consts<>+0x00(SB), CONSTBASE
MOVD $16, R8
MOVD $32, R9
MOVD $48, R10
MOVD $64, R11
SRD $6, LEN, BLOCKS
// V16
LXVW4X (CONSTBASE)(R0), VS48
ADD $80,CONSTBASE
// Load key into V17,V18
LXVW4X (KEY)(R0), VS49
LXVW4X (KEY)(R8), VS50
// Load CNT, NONCE into V19
LXVW4X (CNT)(R0), VS51
// Clear V27
VXOR V27, V27, V27
// V28
LXVW4X (CONSTBASE)(R11), VS60
// splat slot from V19 -> V26
VSPLTW $0, V19, V26
VSLDOI $4, V19, V27, V19
VSLDOI $12, V27, V19, V19
VADDUWM V26, V28, V26
MOVD $10, R14
MOVD R14, CTR
loop_outer_vsx:
// V0, V1, V2, V3
LXVW4X (R0)(CONSTBASE), VS32
LXVW4X (R8)(CONSTBASE), VS33
LXVW4X (R9)(CONSTBASE), VS34
LXVW4X (R10)(CONSTBASE), VS35
// splat values from V17, V18 into V4-V11
VSPLTW $0, V17, V4
VSPLTW $1, V17, V5
VSPLTW $2, V17, V6
VSPLTW $3, V17, V7
VSPLTW $0, V18, V8
VSPLTW $1, V18, V9
VSPLTW $2, V18, V10
VSPLTW $3, V18, V11
// VOR
VOR V26, V26, V12
// splat values from V19 -> V13, V14, V15
VSPLTW $1, V19, V13
VSPLTW $2, V19, V14
VSPLTW $3, V19, V15
// splat const values
VSPLTISW $-16, V27
VSPLTISW $12, V28
VSPLTISW $8, V29
VSPLTISW $7, V30
loop_vsx:
VADDUWM V0, V4, V0
VADDUWM V1, V5, V1
VADDUWM V2, V6, V2
VADDUWM V3, V7, V3
VXOR V12, V0, V12
VXOR V13, V1, V13
VXOR V14, V2, V14
VXOR V15, V3, V15
VRLW V12, V27, V12
VRLW V13, V27, V13
VRLW V14, V27, V14
VRLW V15, V27, V15
VADDUWM V8, V12, V8
VADDUWM V9, V13, V9
VADDUWM V10, V14, V10
VADDUWM V11, V15, V11
VXOR V4, V8, V4
VXOR V5, V9, V5
VXOR V6, V10, V6
VXOR V7, V11, V7
VRLW V4, V28, V4
VRLW V5, V28, V5
VRLW V6, V28, V6
VRLW V7, V28, V7
VADDUWM V0, V4, V0
VADDUWM V1, V5, V1
VADDUWM V2, V6, V2
VADDUWM V3, V7, V3
VXOR V12, V0, V12
VXOR V13, V1, V13
VXOR V14, V2, V14
VXOR V15, V3, V15
VRLW V12, V29, V12
VRLW V13, V29, V13
VRLW V14, V29, V14
VRLW V15, V29, V15
VADDUWM V8, V12, V8
VADDUWM V9, V13, V9
VADDUWM V10, V14, V10
VADDUWM V11, V15, V11
VXOR V4, V8, V4
VXOR V5, V9, V5
VXOR V6, V10, V6
VXOR V7, V11, V7
VRLW V4, V30, V4
VRLW V5, V30, V5
VRLW V6, V30, V6
VRLW V7, V30, V7
VADDUWM V0, V5, V0
VADDUWM V1, V6, V1
VADDUWM V2, V7, V2
VADDUWM V3, V4, V3
VXOR V15, V0, V15
VXOR V12, V1, V12
VXOR V13, V2, V13
VXOR V14, V3, V14
VRLW V15, V27, V15
VRLW V12, V27, V12
VRLW V13, V27, V13
VRLW V14, V27, V14
VADDUWM V10, V15, V10
VADDUWM V11, V12, V11
VADDUWM V8, V13, V8
VADDUWM V9, V14, V9
VXOR V5, V10, V5
VXOR V6, V11, V6
VXOR V7, V8, V7
VXOR V4, V9, V4
VRLW V5, V28, V5
VRLW V6, V28, V6
VRLW V7, V28, V7
VRLW V4, V28, V4
VADDUWM V0, V5, V0
VADDUWM V1, V6, V1
VADDUWM V2, V7, V2
VADDUWM V3, V4, V3
VXOR V15, V0, V15
VXOR V12, V1, V12
VXOR V13, V2, V13
VXOR V14, V3, V14
VRLW V15, V29, V15
VRLW V12, V29, V12
VRLW V13, V29, V13
VRLW V14, V29, V14
VADDUWM V10, V15, V10
VADDUWM V11, V12, V11
VADDUWM V8, V13, V8
VADDUWM V9, V14, V9
VXOR V5, V10, V5
VXOR V6, V11, V6
VXOR V7, V8, V7
VXOR V4, V9, V4
VRLW V5, V30, V5
VRLW V6, V30, V6
VRLW V7, V30, V7
VRLW V4, V30, V4
BC 16, LT, loop_vsx
VADDUWM V12, V26, V12
WORD $0x13600F8C // VMRGEW V0, V1, V27
WORD $0x13821F8C // VMRGEW V2, V3, V28
WORD $0x10000E8C // VMRGOW V0, V1, V0
WORD $0x10421E8C // VMRGOW V2, V3, V2
WORD $0x13A42F8C // VMRGEW V4, V5, V29
WORD $0x13C63F8C // VMRGEW V6, V7, V30
XXPERMDI VS32, VS34, $0, VS33
XXPERMDI VS32, VS34, $3, VS35
XXPERMDI VS59, VS60, $0, VS32
XXPERMDI VS59, VS60, $3, VS34
WORD $0x10842E8C // VMRGOW V4, V5, V4
WORD $0x10C63E8C // VMRGOW V6, V7, V6
WORD $0x13684F8C // VMRGEW V8, V9, V27
WORD $0x138A5F8C // VMRGEW V10, V11, V28
XXPERMDI VS36, VS38, $0, VS37
XXPERMDI VS36, VS38, $3, VS39
XXPERMDI VS61, VS62, $0, VS36
XXPERMDI VS61, VS62, $3, VS38
WORD $0x11084E8C // VMRGOW V8, V9, V8
WORD $0x114A5E8C // VMRGOW V10, V11, V10
WORD $0x13AC6F8C // VMRGEW V12, V13, V29
WORD $0x13CE7F8C // VMRGEW V14, V15, V30
XXPERMDI VS40, VS42, $0, VS41
XXPERMDI VS40, VS42, $3, VS43
XXPERMDI VS59, VS60, $0, VS40
XXPERMDI VS59, VS60, $3, VS42
WORD $0x118C6E8C // VMRGOW V12, V13, V12
WORD $0x11CE7E8C // VMRGOW V14, V15, V14
VSPLTISW $4, V27
VADDUWM V26, V27, V26
XXPERMDI VS44, VS46, $0, VS45
XXPERMDI VS44, VS46, $3, VS47
XXPERMDI VS61, VS62, $0, VS44
XXPERMDI VS61, VS62, $3, VS46
VADDUWM V0, V16, V0
VADDUWM V4, V17, V4
VADDUWM V8, V18, V8
VADDUWM V12, V19, V12
CMPU LEN, $64
BLT tail_vsx
// Bottom of loop
LXVW4X (INP)(R0), VS59
LXVW4X (INP)(R8), VS60
LXVW4X (INP)(R9), VS61
LXVW4X (INP)(R10), VS62
VXOR V27, V0, V27
VXOR V28, V4, V28
VXOR V29, V8, V29
VXOR V30, V12, V30
STXVW4X VS59, (OUT)(R0)
STXVW4X VS60, (OUT)(R8)
ADD $64, INP
STXVW4X VS61, (OUT)(R9)
ADD $-64, LEN
STXVW4X VS62, (OUT)(R10)
ADD $64, OUT
BEQ done_vsx
VADDUWM V1, V16, V0
VADDUWM V5, V17, V4
VADDUWM V9, V18, V8
VADDUWM V13, V19, V12
CMPU LEN, $64
BLT tail_vsx
LXVW4X (INP)(R0), VS59
LXVW4X (INP)(R8), VS60
LXVW4X (INP)(R9), VS61
LXVW4X (INP)(R10), VS62
VXOR V27, V0, V27
VXOR V28, V4, V28
VXOR V29, V8, V29
VXOR V30, V12, V30
STXVW4X VS59, (OUT)(R0)
STXVW4X VS60, (OUT)(R8)
ADD $64, INP
STXVW4X VS61, (OUT)(R9)
ADD $-64, LEN
STXVW4X VS62, (OUT)(V10)
ADD $64, OUT
BEQ done_vsx
VADDUWM V2, V16, V0
VADDUWM V6, V17, V4
VADDUWM V10, V18, V8
VADDUWM V14, V19, V12
CMPU LEN, $64
BLT tail_vsx
LXVW4X (INP)(R0), VS59
LXVW4X (INP)(R8), VS60
LXVW4X (INP)(R9), VS61
LXVW4X (INP)(R10), VS62
VXOR V27, V0, V27
VXOR V28, V4, V28
VXOR V29, V8, V29
VXOR V30, V12, V30
STXVW4X VS59, (OUT)(R0)
STXVW4X VS60, (OUT)(R8)
ADD $64, INP
STXVW4X VS61, (OUT)(R9)
ADD $-64, LEN
STXVW4X VS62, (OUT)(R10)
ADD $64, OUT
BEQ done_vsx
VADDUWM V3, V16, V0
VADDUWM V7, V17, V4
VADDUWM V11, V18, V8
VADDUWM V15, V19, V12
CMPU LEN, $64
BLT tail_vsx
LXVW4X (INP)(R0), VS59
LXVW4X (INP)(R8), VS60
LXVW4X (INP)(R9), VS61
LXVW4X (INP)(R10), VS62
VXOR V27, V0, V27
VXOR V28, V4, V28
VXOR V29, V8, V29
VXOR V30, V12, V30
STXVW4X VS59, (OUT)(R0)
STXVW4X VS60, (OUT)(R8)
ADD $64, INP
STXVW4X VS61, (OUT)(R9)
ADD $-64, LEN
STXVW4X VS62, (OUT)(R10)
ADD $64, OUT
MOVD $10, R14
MOVD R14, CTR
BNE loop_outer_vsx
done_vsx:
// Increment counter by number of 64 byte blocks
MOVD (CNT), R14
ADD BLOCKS, R14
MOVD R14, (CNT)
RET
tail_vsx:
ADD $32, R1, R11
MOVD LEN, CTR
// Save values on stack to copy from
STXVW4X VS32, (R11)(R0)
STXVW4X VS36, (R11)(R8)
STXVW4X VS40, (R11)(R9)
STXVW4X VS44, (R11)(R10)
ADD $-1, R11, R12
ADD $-1, INP
ADD $-1, OUT
looptail_vsx:
// Copying the result to OUT
// in bytes.
MOVBZU 1(R12), KEY
MOVBZU 1(INP), TMP
XOR KEY, TMP, KEY
MOVBU KEY, 1(OUT)
BC 16, LT, looptail_vsx
// Clear the stack values
STXVW4X VS48, (R11)(R0)
STXVW4X VS48, (R11)(R8)
STXVW4X VS48, (R11)(R9)
STXVW4X VS48, (R11)(R10)
BR done_vsx

View File

@ -1,26 +0,0 @@
// 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,!purego
package chacha20
import "golang.org/x/sys/cpu"
var haveAsm = cpu.S390X.HasVX
const bufSize = 256
// xorKeyStreamVX is an assembly implementation of XORKeyStream. It must only
// be called when the vector facility is available. Implementation in asm_s390x.s.
//go:noescape
func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32)
func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) {
if cpu.S390X.HasVX {
xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter)
} else {
c.xorKeyStreamBlocksGeneric(dst, src)
}
}

View File

@ -81,7 +81,7 @@ func (b *Builder) AddASN1BigInt(n *big.Int) {
for i := range bytes { for i := range bytes {
bytes[i] ^= 0xff bytes[i] ^= 0xff
} }
if len(bytes) == 0 || bytes[0]&0x80 == 0 { if bytes[0]&0x80 == 0 {
c.add(0xff) c.add(0xff)
} }
c.add(bytes...) c.add(bytes...)
@ -230,12 +230,12 @@ func (b *Builder) AddASN1(tag asn1.Tag, f BuilderContinuation) {
// String // String
// ReadASN1Boolean decodes an ASN.1 BOOLEAN and converts it to a boolean // ReadASN1Boolean decodes an ASN.1 INTEGER and converts it to a boolean
// representation into out and advances. It reports whether the read // representation into out and advances. It reports whether the read
// was successful. // was successful.
func (s *String) ReadASN1Boolean(out *bool) bool { func (s *String) ReadASN1Boolean(out *bool) bool {
var bytes String var bytes String
if !s.ReadASN1(&bytes, asn1.BOOLEAN) || len(bytes) != 1 { if !s.ReadASN1(&bytes, asn1.INTEGER) || len(bytes) != 1 {
return false return false
} }
@ -470,8 +470,7 @@ func (s *String) ReadASN1GeneralizedTime(out *time.Time) bool {
// It reports whether the read was successful. // It reports whether the read was successful.
func (s *String) ReadASN1BitString(out *encoding_asn1.BitString) bool { func (s *String) ReadASN1BitString(out *encoding_asn1.BitString) bool {
var bytes String var bytes String
if !s.ReadASN1(&bytes, asn1.BIT_STRING) || len(bytes) == 0 || if !s.ReadASN1(&bytes, asn1.BIT_STRING) || len(bytes) == 0 {
len(bytes)*8/8 != len(bytes) {
return false return false
} }
@ -741,7 +740,7 @@ func (s *String) readASN1(out *String, outTag *asn1.Tag, skipHeader bool) bool {
length = headerLen + len32 length = headerLen + len32
} }
if int(length) < 0 || !s.ReadBytes((*[]byte)(out), int(length)) { if uint32(int(length)) != length || !s.ReadBytes((*[]byte)(out), int(length)) {
return false return false
} }
if skipHeader && !out.Skip(int(headerLen)) { if skipHeader && !out.Skip(int(headerLen)) {

View File

@ -24,7 +24,7 @@ type String []byte
// read advances a String by n bytes and returns them. If less than n bytes // read advances a String by n bytes and returns them. If less than n bytes
// remain, it returns nil. // remain, it returns nil.
func (s *String) read(n int) []byte { func (s *String) read(n int) []byte {
if len(*s) < n || n < 0 { if len(*s) < n {
return nil return nil
} }
v := (*s)[:n] v := (*s)[:n]
@ -105,6 +105,11 @@ func (s *String) readLengthPrefixed(lenLen int, outChild *String) bool {
length = length << 8 length = length << 8
length = length | uint32(b) length = length | uint32(b)
} }
if int(length) < 0 {
// This currently cannot overflow because we read uint24 at most, but check
// anyway in case that changes in the future.
return false
}
v := s.read(int(length)) v := s.read(int(length))
if v == nil { if v == nil {
return false return false

8
vendor/golang.org/x/crypto/curve25519/const_amd64.h generated vendored Normal file
View File

@ -0,0 +1,8 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This code was translated into a form compatible with 6a from the public
// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
#define REDMASK51 0x0007FFFFFFFFFFFF

20
vendor/golang.org/x/crypto/curve25519/const_amd64.s generated vendored Normal file
View File

@ -0,0 +1,20 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This code was translated into a form compatible with 6a from the public
// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
// +build amd64,!gccgo,!appengine
// These constants cannot be encoded in non-MOVQ immediates.
// We access them directly from memory instead.
DATA ·_121666_213(SB)/8, $996687872
GLOBL ·_121666_213(SB), 8, $8
DATA ·_2P0(SB)/8, $0xFFFFFFFFFFFDA
GLOBL ·_2P0(SB), 8, $8
DATA ·_2P1234(SB)/8, $0xFFFFFFFFFFFFE
GLOBL ·_2P1234(SB), 8, $8

65
vendor/golang.org/x/crypto/curve25519/cswap_amd64.s generated vendored Normal file
View File

@ -0,0 +1,65 @@
// Copyright 2012 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 amd64,!gccgo,!appengine
// func cswap(inout *[4][5]uint64, v uint64)
TEXT ·cswap(SB),7,$0
MOVQ inout+0(FP),DI
MOVQ v+8(FP),SI
SUBQ $1, SI
NOTQ SI
MOVQ SI, X15
PSHUFD $0x44, X15, X15
MOVOU 0(DI), X0
MOVOU 16(DI), X2
MOVOU 32(DI), X4
MOVOU 48(DI), X6
MOVOU 64(DI), X8
MOVOU 80(DI), X1
MOVOU 96(DI), X3
MOVOU 112(DI), X5
MOVOU 128(DI), X7
MOVOU 144(DI), X9
MOVO X1, X10
MOVO X3, X11
MOVO X5, X12
MOVO X7, X13
MOVO X9, X14
PXOR X0, X10
PXOR X2, X11
PXOR X4, X12
PXOR X6, X13
PXOR X8, X14
PAND X15, X10
PAND X15, X11
PAND X15, X12
PAND X15, X13
PAND X15, X14
PXOR X10, X0
PXOR X10, X1
PXOR X11, X2
PXOR X11, X3
PXOR X12, X4
PXOR X12, X5
PXOR X13, X6
PXOR X13, X7
PXOR X14, X8
PXOR X14, X9
MOVOU X0, 0(DI)
MOVOU X2, 16(DI)
MOVOU X4, 32(DI)
MOVOU X6, 48(DI)
MOVOU X8, 64(DI)
MOVOU X1, 80(DI)
MOVOU X3, 96(DI)
MOVOU X5, 112(DI)
MOVOU X7, 128(DI)
MOVOU X9, 144(DI)
RET

View File

@ -1,95 +1,834 @@
// Copyright 2019 The Go Authors. All rights reserved. // Copyright 2013 The Go Authors. All rights reserved.
// 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.
// Package curve25519 provides an implementation of the X25519 function, which // We have an implementation in amd64 assembly so this code is only run on
// performs scalar multiplication on the elliptic curve known as Curve25519. // non-amd64 platforms. The amd64 assembly does not support gccgo.
// See RFC 7748. // +build !amd64 gccgo appengine
package curve25519 // import "golang.org/x/crypto/curve25519"
package curve25519
import ( import (
"crypto/subtle" "encoding/binary"
"fmt"
) )
// ScalarMult sets dst to the product scalar * point. // This code is a port of the public domain, "ref10" implementation of
// // curve25519 from SUPERCOP 20130419 by D. J. Bernstein.
// Deprecated: when provided a low-order point, ScalarMult will set dst to all
// zeroes, irrespective of the scalar. Instead, use the X25519 function, which
// will return an error.
func ScalarMult(dst, scalar, point *[32]byte) {
scalarMult(dst, scalar, point)
}
// ScalarBaseMult sets dst to the product scalar * base where base is the // fieldElement represents an element of the field GF(2^255 - 19). An element
// standard generator. // t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
// // t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on
// It is recommended to use the X25519 function with Basepoint instead, as // context.
// copying into fixed size arrays can lead to unexpected bugs. type fieldElement [10]int32
func ScalarBaseMult(dst, scalar *[32]byte) {
ScalarMult(dst, scalar, &basePoint)
}
const ( func feZero(fe *fieldElement) {
// ScalarSize is the size of the scalar input to X25519. for i := range fe {
ScalarSize = 32 fe[i] = 0
// PointSize is the size of the point input to X25519.
PointSize = 32
)
// Basepoint is the canonical Curve25519 generator.
var Basepoint []byte
var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
func init() { Basepoint = basePoint[:] }
func checkBasepoint() {
if subtle.ConstantTimeCompare(Basepoint, []byte{
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
}) != 1 {
panic("curve25519: global Basepoint value was modified")
} }
} }
// X25519 returns the result of the scalar multiplication (scalar * point), func feOne(fe *fieldElement) {
// according to RFC 7748, Section 5. scalar, point and the return value are feZero(fe)
// slices of 32 bytes. fe[0] = 1
//
// scalar can be generated at random, for example with crypto/rand. point should
// be either Basepoint or the output of another X25519 call.
//
// If point is Basepoint (but not if it's a different slice with the same
// contents) a precomputed implementation might be used for performance.
func X25519(scalar, point []byte) ([]byte, error) {
// Outline the body of function, to let the allocation be inlined in the
// caller, and possibly avoid escaping to the heap.
var dst [32]byte
return x25519(&dst, scalar, point)
} }
func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) { func feAdd(dst, a, b *fieldElement) {
var in [32]byte for i := range dst {
if l := len(scalar); l != 32 { dst[i] = a[i] + b[i]
return nil, fmt.Errorf("bad scalar length: %d, expected %d", l, 32)
} }
if l := len(point); l != 32 { }
return nil, fmt.Errorf("bad point length: %d, expected %d", l, 32)
} func feSub(dst, a, b *fieldElement) {
copy(in[:], scalar) for i := range dst {
if &point[0] == &Basepoint[0] { dst[i] = a[i] - b[i]
checkBasepoint() }
ScalarBaseMult(dst, &in) }
} else {
var base, zero [32]byte func feCopy(dst, src *fieldElement) {
copy(base[:], point) for i := range dst {
ScalarMult(dst, &in, &base) dst[i] = src[i]
if subtle.ConstantTimeCompare(dst[:], zero[:]) == 1 { }
return nil, fmt.Errorf("bad input point: low order point") }
}
} // feCSwap replaces (f,g) with (g,f) if b == 1; replaces (f,g) with (f,g) if b == 0.
return dst[:], nil //
// Preconditions: b in {0,1}.
func feCSwap(f, g *fieldElement, b int32) {
b = -b
for i := range f {
t := b & (f[i] ^ g[i])
f[i] ^= t
g[i] ^= t
}
}
// load3 reads a 24-bit, little-endian value from in.
func load3(in []byte) int64 {
var r int64
r = int64(in[0])
r |= int64(in[1]) << 8
r |= int64(in[2]) << 16
return r
}
// load4 reads a 32-bit, little-endian value from in.
func load4(in []byte) int64 {
return int64(binary.LittleEndian.Uint32(in))
}
func feFromBytes(dst *fieldElement, src *[32]byte) {
h0 := load4(src[:])
h1 := load3(src[4:]) << 6
h2 := load3(src[7:]) << 5
h3 := load3(src[10:]) << 3
h4 := load3(src[13:]) << 2
h5 := load4(src[16:])
h6 := load3(src[20:]) << 7
h7 := load3(src[23:]) << 5
h8 := load3(src[26:]) << 4
h9 := (load3(src[29:]) & 0x7fffff) << 2
var carry [10]int64
carry[9] = (h9 + 1<<24) >> 25
h0 += carry[9] * 19
h9 -= carry[9] << 25
carry[1] = (h1 + 1<<24) >> 25
h2 += carry[1]
h1 -= carry[1] << 25
carry[3] = (h3 + 1<<24) >> 25
h4 += carry[3]
h3 -= carry[3] << 25
carry[5] = (h5 + 1<<24) >> 25
h6 += carry[5]
h5 -= carry[5] << 25
carry[7] = (h7 + 1<<24) >> 25
h8 += carry[7]
h7 -= carry[7] << 25
carry[0] = (h0 + 1<<25) >> 26
h1 += carry[0]
h0 -= carry[0] << 26
carry[2] = (h2 + 1<<25) >> 26
h3 += carry[2]
h2 -= carry[2] << 26
carry[4] = (h4 + 1<<25) >> 26
h5 += carry[4]
h4 -= carry[4] << 26
carry[6] = (h6 + 1<<25) >> 26
h7 += carry[6]
h6 -= carry[6] << 26
carry[8] = (h8 + 1<<25) >> 26
h9 += carry[8]
h8 -= carry[8] << 26
dst[0] = int32(h0)
dst[1] = int32(h1)
dst[2] = int32(h2)
dst[3] = int32(h3)
dst[4] = int32(h4)
dst[5] = int32(h5)
dst[6] = int32(h6)
dst[7] = int32(h7)
dst[8] = int32(h8)
dst[9] = int32(h9)
}
// feToBytes marshals h to s.
// Preconditions:
// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
//
// Write p=2^255-19; q=floor(h/p).
// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))).
//
// Proof:
// Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4.
// Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4.
//
// Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9).
// Then 0<y<1.
//
// Write r=h-pq.
// Have 0<=r<=p-1=2^255-20.
// Thus 0<=r+19(2^-255)r<r+19(2^-255)2^255<=2^255-1.
//
// Write x=r+19(2^-255)r+y.
// Then 0<x<2^255 so floor(2^(-255)x) = 0 so floor(q+2^(-255)x) = q.
//
// Have q+2^(-255)x = 2^(-255)(h + 19 2^(-25) h9 + 2^(-1))
// so floor(2^(-255)(h + 19 2^(-25) h9 + 2^(-1))) = q.
func feToBytes(s *[32]byte, h *fieldElement) {
var carry [10]int32
q := (19*h[9] + (1 << 24)) >> 25
q = (h[0] + q) >> 26
q = (h[1] + q) >> 25
q = (h[2] + q) >> 26
q = (h[3] + q) >> 25
q = (h[4] + q) >> 26
q = (h[5] + q) >> 25
q = (h[6] + q) >> 26
q = (h[7] + q) >> 25
q = (h[8] + q) >> 26
q = (h[9] + q) >> 25
// Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20.
h[0] += 19 * q
// Goal: Output h-2^255 q, which is between 0 and 2^255-20.
carry[0] = h[0] >> 26
h[1] += carry[0]
h[0] -= carry[0] << 26
carry[1] = h[1] >> 25
h[2] += carry[1]
h[1] -= carry[1] << 25
carry[2] = h[2] >> 26
h[3] += carry[2]
h[2] -= carry[2] << 26
carry[3] = h[3] >> 25
h[4] += carry[3]
h[3] -= carry[3] << 25
carry[4] = h[4] >> 26
h[5] += carry[4]
h[4] -= carry[4] << 26
carry[5] = h[5] >> 25
h[6] += carry[5]
h[5] -= carry[5] << 25
carry[6] = h[6] >> 26
h[7] += carry[6]
h[6] -= carry[6] << 26
carry[7] = h[7] >> 25
h[8] += carry[7]
h[7] -= carry[7] << 25
carry[8] = h[8] >> 26
h[9] += carry[8]
h[8] -= carry[8] << 26
carry[9] = h[9] >> 25
h[9] -= carry[9] << 25
// h10 = carry9
// Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
// Have h[0]+...+2^230 h[9] between 0 and 2^255-1;
// evidently 2^255 h10-2^255 q = 0.
// Goal: Output h[0]+...+2^230 h[9].
s[0] = byte(h[0] >> 0)
s[1] = byte(h[0] >> 8)
s[2] = byte(h[0] >> 16)
s[3] = byte((h[0] >> 24) | (h[1] << 2))
s[4] = byte(h[1] >> 6)
s[5] = byte(h[1] >> 14)
s[6] = byte((h[1] >> 22) | (h[2] << 3))
s[7] = byte(h[2] >> 5)
s[8] = byte(h[2] >> 13)
s[9] = byte((h[2] >> 21) | (h[3] << 5))
s[10] = byte(h[3] >> 3)
s[11] = byte(h[3] >> 11)
s[12] = byte((h[3] >> 19) | (h[4] << 6))
s[13] = byte(h[4] >> 2)
s[14] = byte(h[4] >> 10)
s[15] = byte(h[4] >> 18)
s[16] = byte(h[5] >> 0)
s[17] = byte(h[5] >> 8)
s[18] = byte(h[5] >> 16)
s[19] = byte((h[5] >> 24) | (h[6] << 1))
s[20] = byte(h[6] >> 7)
s[21] = byte(h[6] >> 15)
s[22] = byte((h[6] >> 23) | (h[7] << 3))
s[23] = byte(h[7] >> 5)
s[24] = byte(h[7] >> 13)
s[25] = byte((h[7] >> 21) | (h[8] << 4))
s[26] = byte(h[8] >> 4)
s[27] = byte(h[8] >> 12)
s[28] = byte((h[8] >> 20) | (h[9] << 6))
s[29] = byte(h[9] >> 2)
s[30] = byte(h[9] >> 10)
s[31] = byte(h[9] >> 18)
}
// feMul calculates h = f * g
// Can overlap h with f or g.
//
// Preconditions:
// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
// |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
//
// Postconditions:
// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
//
// Notes on implementation strategy:
//
// Using schoolbook multiplication.
// Karatsuba would save a little in some cost models.
//
// Most multiplications by 2 and 19 are 32-bit precomputations;
// cheaper than 64-bit postcomputations.
//
// There is one remaining multiplication by 19 in the carry chain;
// one *19 precomputation can be merged into this,
// but the resulting data flow is considerably less clean.
//
// There are 12 carries below.
// 10 of them are 2-way parallelizable and vectorizable.
// Can get away with 11 carries, but then data flow is much deeper.
//
// With tighter constraints on inputs can squeeze carries into int32.
func feMul(h, f, g *fieldElement) {
f0 := f[0]
f1 := f[1]
f2 := f[2]
f3 := f[3]
f4 := f[4]
f5 := f[5]
f6 := f[6]
f7 := f[7]
f8 := f[8]
f9 := f[9]
g0 := g[0]
g1 := g[1]
g2 := g[2]
g3 := g[3]
g4 := g[4]
g5 := g[5]
g6 := g[6]
g7 := g[7]
g8 := g[8]
g9 := g[9]
g1_19 := 19 * g1 // 1.4*2^29
g2_19 := 19 * g2 // 1.4*2^30; still ok
g3_19 := 19 * g3
g4_19 := 19 * g4
g5_19 := 19 * g5
g6_19 := 19 * g6
g7_19 := 19 * g7
g8_19 := 19 * g8
g9_19 := 19 * g9
f1_2 := 2 * f1
f3_2 := 2 * f3
f5_2 := 2 * f5
f7_2 := 2 * f7
f9_2 := 2 * f9
f0g0 := int64(f0) * int64(g0)
f0g1 := int64(f0) * int64(g1)
f0g2 := int64(f0) * int64(g2)
f0g3 := int64(f0) * int64(g3)
f0g4 := int64(f0) * int64(g4)
f0g5 := int64(f0) * int64(g5)
f0g6 := int64(f0) * int64(g6)
f0g7 := int64(f0) * int64(g7)
f0g8 := int64(f0) * int64(g8)
f0g9 := int64(f0) * int64(g9)
f1g0 := int64(f1) * int64(g0)
f1g1_2 := int64(f1_2) * int64(g1)
f1g2 := int64(f1) * int64(g2)
f1g3_2 := int64(f1_2) * int64(g3)
f1g4 := int64(f1) * int64(g4)
f1g5_2 := int64(f1_2) * int64(g5)
f1g6 := int64(f1) * int64(g6)
f1g7_2 := int64(f1_2) * int64(g7)
f1g8 := int64(f1) * int64(g8)
f1g9_38 := int64(f1_2) * int64(g9_19)
f2g0 := int64(f2) * int64(g0)
f2g1 := int64(f2) * int64(g1)
f2g2 := int64(f2) * int64(g2)
f2g3 := int64(f2) * int64(g3)
f2g4 := int64(f2) * int64(g4)
f2g5 := int64(f2) * int64(g5)
f2g6 := int64(f2) * int64(g6)
f2g7 := int64(f2) * int64(g7)
f2g8_19 := int64(f2) * int64(g8_19)
f2g9_19 := int64(f2) * int64(g9_19)
f3g0 := int64(f3) * int64(g0)
f3g1_2 := int64(f3_2) * int64(g1)
f3g2 := int64(f3) * int64(g2)
f3g3_2 := int64(f3_2) * int64(g3)
f3g4 := int64(f3) * int64(g4)
f3g5_2 := int64(f3_2) * int64(g5)
f3g6 := int64(f3) * int64(g6)
f3g7_38 := int64(f3_2) * int64(g7_19)
f3g8_19 := int64(f3) * int64(g8_19)
f3g9_38 := int64(f3_2) * int64(g9_19)
f4g0 := int64(f4) * int64(g0)
f4g1 := int64(f4) * int64(g1)
f4g2 := int64(f4) * int64(g2)
f4g3 := int64(f4) * int64(g3)
f4g4 := int64(f4) * int64(g4)
f4g5 := int64(f4) * int64(g5)
f4g6_19 := int64(f4) * int64(g6_19)
f4g7_19 := int64(f4) * int64(g7_19)
f4g8_19 := int64(f4) * int64(g8_19)
f4g9_19 := int64(f4) * int64(g9_19)
f5g0 := int64(f5) * int64(g0)
f5g1_2 := int64(f5_2) * int64(g1)
f5g2 := int64(f5) * int64(g2)
f5g3_2 := int64(f5_2) * int64(g3)
f5g4 := int64(f5) * int64(g4)
f5g5_38 := int64(f5_2) * int64(g5_19)
f5g6_19 := int64(f5) * int64(g6_19)
f5g7_38 := int64(f5_2) * int64(g7_19)
f5g8_19 := int64(f5) * int64(g8_19)
f5g9_38 := int64(f5_2) * int64(g9_19)
f6g0 := int64(f6) * int64(g0)
f6g1 := int64(f6) * int64(g1)
f6g2 := int64(f6) * int64(g2)
f6g3 := int64(f6) * int64(g3)
f6g4_19 := int64(f6) * int64(g4_19)
f6g5_19 := int64(f6) * int64(g5_19)
f6g6_19 := int64(f6) * int64(g6_19)
f6g7_19 := int64(f6) * int64(g7_19)
f6g8_19 := int64(f6) * int64(g8_19)
f6g9_19 := int64(f6) * int64(g9_19)
f7g0 := int64(f7) * int64(g0)
f7g1_2 := int64(f7_2) * int64(g1)
f7g2 := int64(f7) * int64(g2)
f7g3_38 := int64(f7_2) * int64(g3_19)
f7g4_19 := int64(f7) * int64(g4_19)
f7g5_38 := int64(f7_2) * int64(g5_19)
f7g6_19 := int64(f7) * int64(g6_19)
f7g7_38 := int64(f7_2) * int64(g7_19)
f7g8_19 := int64(f7) * int64(g8_19)
f7g9_38 := int64(f7_2) * int64(g9_19)
f8g0 := int64(f8) * int64(g0)
f8g1 := int64(f8) * int64(g1)
f8g2_19 := int64(f8) * int64(g2_19)
f8g3_19 := int64(f8) * int64(g3_19)
f8g4_19 := int64(f8) * int64(g4_19)
f8g5_19 := int64(f8) * int64(g5_19)
f8g6_19 := int64(f8) * int64(g6_19)
f8g7_19 := int64(f8) * int64(g7_19)
f8g8_19 := int64(f8) * int64(g8_19)
f8g9_19 := int64(f8) * int64(g9_19)
f9g0 := int64(f9) * int64(g0)
f9g1_38 := int64(f9_2) * int64(g1_19)
f9g2_19 := int64(f9) * int64(g2_19)
f9g3_38 := int64(f9_2) * int64(g3_19)
f9g4_19 := int64(f9) * int64(g4_19)
f9g5_38 := int64(f9_2) * int64(g5_19)
f9g6_19 := int64(f9) * int64(g6_19)
f9g7_38 := int64(f9_2) * int64(g7_19)
f9g8_19 := int64(f9) * int64(g8_19)
f9g9_38 := int64(f9_2) * int64(g9_19)
h0 := f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38
h1 := f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19
h2 := f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38
h3 := f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19
h4 := f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38
h5 := f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19
h6 := f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38
h7 := f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19
h8 := f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38
h9 := f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0
var carry [10]int64
// |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38))
// i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8
// |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19))
// i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9
carry[0] = (h0 + (1 << 25)) >> 26
h1 += carry[0]
h0 -= carry[0] << 26
carry[4] = (h4 + (1 << 25)) >> 26
h5 += carry[4]
h4 -= carry[4] << 26
// |h0| <= 2^25
// |h4| <= 2^25
// |h1| <= 1.51*2^58
// |h5| <= 1.51*2^58
carry[1] = (h1 + (1 << 24)) >> 25
h2 += carry[1]
h1 -= carry[1] << 25
carry[5] = (h5 + (1 << 24)) >> 25
h6 += carry[5]
h5 -= carry[5] << 25
// |h1| <= 2^24; from now on fits into int32
// |h5| <= 2^24; from now on fits into int32
// |h2| <= 1.21*2^59
// |h6| <= 1.21*2^59
carry[2] = (h2 + (1 << 25)) >> 26
h3 += carry[2]
h2 -= carry[2] << 26
carry[6] = (h6 + (1 << 25)) >> 26
h7 += carry[6]
h6 -= carry[6] << 26
// |h2| <= 2^25; from now on fits into int32 unchanged
// |h6| <= 2^25; from now on fits into int32 unchanged
// |h3| <= 1.51*2^58
// |h7| <= 1.51*2^58
carry[3] = (h3 + (1 << 24)) >> 25
h4 += carry[3]
h3 -= carry[3] << 25
carry[7] = (h7 + (1 << 24)) >> 25
h8 += carry[7]
h7 -= carry[7] << 25
// |h3| <= 2^24; from now on fits into int32 unchanged
// |h7| <= 2^24; from now on fits into int32 unchanged
// |h4| <= 1.52*2^33
// |h8| <= 1.52*2^33
carry[4] = (h4 + (1 << 25)) >> 26
h5 += carry[4]
h4 -= carry[4] << 26
carry[8] = (h8 + (1 << 25)) >> 26
h9 += carry[8]
h8 -= carry[8] << 26
// |h4| <= 2^25; from now on fits into int32 unchanged
// |h8| <= 2^25; from now on fits into int32 unchanged
// |h5| <= 1.01*2^24
// |h9| <= 1.51*2^58
carry[9] = (h9 + (1 << 24)) >> 25
h0 += carry[9] * 19
h9 -= carry[9] << 25
// |h9| <= 2^24; from now on fits into int32 unchanged
// |h0| <= 1.8*2^37
carry[0] = (h0 + (1 << 25)) >> 26
h1 += carry[0]
h0 -= carry[0] << 26
// |h0| <= 2^25; from now on fits into int32 unchanged
// |h1| <= 1.01*2^24
h[0] = int32(h0)
h[1] = int32(h1)
h[2] = int32(h2)
h[3] = int32(h3)
h[4] = int32(h4)
h[5] = int32(h5)
h[6] = int32(h6)
h[7] = int32(h7)
h[8] = int32(h8)
h[9] = int32(h9)
}
// feSquare calculates h = f*f. Can overlap h with f.
//
// Preconditions:
// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
//
// Postconditions:
// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
func feSquare(h, f *fieldElement) {
f0 := f[0]
f1 := f[1]
f2 := f[2]
f3 := f[3]
f4 := f[4]
f5 := f[5]
f6 := f[6]
f7 := f[7]
f8 := f[8]
f9 := f[9]
f0_2 := 2 * f0
f1_2 := 2 * f1
f2_2 := 2 * f2
f3_2 := 2 * f3
f4_2 := 2 * f4
f5_2 := 2 * f5
f6_2 := 2 * f6
f7_2 := 2 * f7
f5_38 := 38 * f5 // 1.31*2^30
f6_19 := 19 * f6 // 1.31*2^30
f7_38 := 38 * f7 // 1.31*2^30
f8_19 := 19 * f8 // 1.31*2^30
f9_38 := 38 * f9 // 1.31*2^30
f0f0 := int64(f0) * int64(f0)
f0f1_2 := int64(f0_2) * int64(f1)
f0f2_2 := int64(f0_2) * int64(f2)
f0f3_2 := int64(f0_2) * int64(f3)
f0f4_2 := int64(f0_2) * int64(f4)
f0f5_2 := int64(f0_2) * int64(f5)
f0f6_2 := int64(f0_2) * int64(f6)
f0f7_2 := int64(f0_2) * int64(f7)
f0f8_2 := int64(f0_2) * int64(f8)
f0f9_2 := int64(f0_2) * int64(f9)
f1f1_2 := int64(f1_2) * int64(f1)
f1f2_2 := int64(f1_2) * int64(f2)
f1f3_4 := int64(f1_2) * int64(f3_2)
f1f4_2 := int64(f1_2) * int64(f4)
f1f5_4 := int64(f1_2) * int64(f5_2)
f1f6_2 := int64(f1_2) * int64(f6)
f1f7_4 := int64(f1_2) * int64(f7_2)
f1f8_2 := int64(f1_2) * int64(f8)
f1f9_76 := int64(f1_2) * int64(f9_38)
f2f2 := int64(f2) * int64(f2)
f2f3_2 := int64(f2_2) * int64(f3)
f2f4_2 := int64(f2_2) * int64(f4)
f2f5_2 := int64(f2_2) * int64(f5)
f2f6_2 := int64(f2_2) * int64(f6)
f2f7_2 := int64(f2_2) * int64(f7)
f2f8_38 := int64(f2_2) * int64(f8_19)
f2f9_38 := int64(f2) * int64(f9_38)
f3f3_2 := int64(f3_2) * int64(f3)
f3f4_2 := int64(f3_2) * int64(f4)
f3f5_4 := int64(f3_2) * int64(f5_2)
f3f6_2 := int64(f3_2) * int64(f6)
f3f7_76 := int64(f3_2) * int64(f7_38)
f3f8_38 := int64(f3_2) * int64(f8_19)
f3f9_76 := int64(f3_2) * int64(f9_38)
f4f4 := int64(f4) * int64(f4)
f4f5_2 := int64(f4_2) * int64(f5)
f4f6_38 := int64(f4_2) * int64(f6_19)
f4f7_38 := int64(f4) * int64(f7_38)
f4f8_38 := int64(f4_2) * int64(f8_19)
f4f9_38 := int64(f4) * int64(f9_38)
f5f5_38 := int64(f5) * int64(f5_38)
f5f6_38 := int64(f5_2) * int64(f6_19)
f5f7_76 := int64(f5_2) * int64(f7_38)
f5f8_38 := int64(f5_2) * int64(f8_19)
f5f9_76 := int64(f5_2) * int64(f9_38)
f6f6_19 := int64(f6) * int64(f6_19)
f6f7_38 := int64(f6) * int64(f7_38)
f6f8_38 := int64(f6_2) * int64(f8_19)
f6f9_38 := int64(f6) * int64(f9_38)
f7f7_38 := int64(f7) * int64(f7_38)
f7f8_38 := int64(f7_2) * int64(f8_19)
f7f9_76 := int64(f7_2) * int64(f9_38)
f8f8_19 := int64(f8) * int64(f8_19)
f8f9_38 := int64(f8) * int64(f9_38)
f9f9_38 := int64(f9) * int64(f9_38)
h0 := f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38
h1 := f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38
h2 := f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19
h3 := f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38
h4 := f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38
h5 := f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38
h6 := f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19
h7 := f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38
h8 := f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38
h9 := f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2
var carry [10]int64
carry[0] = (h0 + (1 << 25)) >> 26
h1 += carry[0]
h0 -= carry[0] << 26
carry[4] = (h4 + (1 << 25)) >> 26
h5 += carry[4]
h4 -= carry[4] << 26
carry[1] = (h1 + (1 << 24)) >> 25
h2 += carry[1]
h1 -= carry[1] << 25
carry[5] = (h5 + (1 << 24)) >> 25
h6 += carry[5]
h5 -= carry[5] << 25
carry[2] = (h2 + (1 << 25)) >> 26
h3 += carry[2]
h2 -= carry[2] << 26
carry[6] = (h6 + (1 << 25)) >> 26
h7 += carry[6]
h6 -= carry[6] << 26
carry[3] = (h3 + (1 << 24)) >> 25
h4 += carry[3]
h3 -= carry[3] << 25
carry[7] = (h7 + (1 << 24)) >> 25
h8 += carry[7]
h7 -= carry[7] << 25
carry[4] = (h4 + (1 << 25)) >> 26
h5 += carry[4]
h4 -= carry[4] << 26
carry[8] = (h8 + (1 << 25)) >> 26
h9 += carry[8]
h8 -= carry[8] << 26
carry[9] = (h9 + (1 << 24)) >> 25
h0 += carry[9] * 19
h9 -= carry[9] << 25
carry[0] = (h0 + (1 << 25)) >> 26
h1 += carry[0]
h0 -= carry[0] << 26
h[0] = int32(h0)
h[1] = int32(h1)
h[2] = int32(h2)
h[3] = int32(h3)
h[4] = int32(h4)
h[5] = int32(h5)
h[6] = int32(h6)
h[7] = int32(h7)
h[8] = int32(h8)
h[9] = int32(h9)
}
// feMul121666 calculates h = f * 121666. Can overlap h with f.
//
// Preconditions:
// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
//
// Postconditions:
// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
func feMul121666(h, f *fieldElement) {
h0 := int64(f[0]) * 121666
h1 := int64(f[1]) * 121666
h2 := int64(f[2]) * 121666
h3 := int64(f[3]) * 121666
h4 := int64(f[4]) * 121666
h5 := int64(f[5]) * 121666
h6 := int64(f[6]) * 121666
h7 := int64(f[7]) * 121666
h8 := int64(f[8]) * 121666
h9 := int64(f[9]) * 121666
var carry [10]int64
carry[9] = (h9 + (1 << 24)) >> 25
h0 += carry[9] * 19
h9 -= carry[9] << 25
carry[1] = (h1 + (1 << 24)) >> 25
h2 += carry[1]
h1 -= carry[1] << 25
carry[3] = (h3 + (1 << 24)) >> 25
h4 += carry[3]
h3 -= carry[3] << 25
carry[5] = (h5 + (1 << 24)) >> 25
h6 += carry[5]
h5 -= carry[5] << 25
carry[7] = (h7 + (1 << 24)) >> 25
h8 += carry[7]
h7 -= carry[7] << 25
carry[0] = (h0 + (1 << 25)) >> 26
h1 += carry[0]
h0 -= carry[0] << 26
carry[2] = (h2 + (1 << 25)) >> 26
h3 += carry[2]
h2 -= carry[2] << 26
carry[4] = (h4 + (1 << 25)) >> 26
h5 += carry[4]
h4 -= carry[4] << 26
carry[6] = (h6 + (1 << 25)) >> 26
h7 += carry[6]
h6 -= carry[6] << 26
carry[8] = (h8 + (1 << 25)) >> 26
h9 += carry[8]
h8 -= carry[8] << 26
h[0] = int32(h0)
h[1] = int32(h1)
h[2] = int32(h2)
h[3] = int32(h3)
h[4] = int32(h4)
h[5] = int32(h5)
h[6] = int32(h6)
h[7] = int32(h7)
h[8] = int32(h8)
h[9] = int32(h9)
}
// feInvert sets out = z^-1.
func feInvert(out, z *fieldElement) {
var t0, t1, t2, t3 fieldElement
var i int
feSquare(&t0, z)
for i = 1; i < 1; i++ {
feSquare(&t0, &t0)
}
feSquare(&t1, &t0)
for i = 1; i < 2; i++ {
feSquare(&t1, &t1)
}
feMul(&t1, z, &t1)
feMul(&t0, &t0, &t1)
feSquare(&t2, &t0)
for i = 1; i < 1; i++ {
feSquare(&t2, &t2)
}
feMul(&t1, &t1, &t2)
feSquare(&t2, &t1)
for i = 1; i < 5; i++ {
feSquare(&t2, &t2)
}
feMul(&t1, &t2, &t1)
feSquare(&t2, &t1)
for i = 1; i < 10; i++ {
feSquare(&t2, &t2)
}
feMul(&t2, &t2, &t1)
feSquare(&t3, &t2)
for i = 1; i < 20; i++ {
feSquare(&t3, &t3)
}
feMul(&t2, &t3, &t2)
feSquare(&t2, &t2)
for i = 1; i < 10; i++ {
feSquare(&t2, &t2)
}
feMul(&t1, &t2, &t1)
feSquare(&t2, &t1)
for i = 1; i < 50; i++ {
feSquare(&t2, &t2)
}
feMul(&t2, &t2, &t1)
feSquare(&t3, &t2)
for i = 1; i < 100; i++ {
feSquare(&t3, &t3)
}
feMul(&t2, &t3, &t2)
feSquare(&t2, &t2)
for i = 1; i < 50; i++ {
feSquare(&t2, &t2)
}
feMul(&t1, &t2, &t1)
feSquare(&t1, &t1)
for i = 1; i < 5; i++ {
feSquare(&t1, &t1)
}
feMul(out, &t1, &t0)
}
func scalarMult(out, in, base *[32]byte) {
var e [32]byte
copy(e[:], in[:])
e[0] &= 248
e[31] &= 127
e[31] |= 64
var x1, x2, z2, x3, z3, tmp0, tmp1 fieldElement
feFromBytes(&x1, base)
feOne(&x2)
feCopy(&x3, &x1)
feOne(&z3)
swap := int32(0)
for pos := 254; pos >= 0; pos-- {
b := e[pos/8] >> uint(pos&7)
b &= 1
swap ^= int32(b)
feCSwap(&x2, &x3, swap)
feCSwap(&z2, &z3, swap)
swap = int32(b)
feSub(&tmp0, &x3, &z3)
feSub(&tmp1, &x2, &z2)
feAdd(&x2, &x2, &z2)
feAdd(&z2, &x3, &z3)
feMul(&z3, &tmp0, &x2)
feMul(&z2, &z2, &tmp1)
feSquare(&tmp0, &tmp1)
feSquare(&tmp1, &x2)
feAdd(&x3, &z3, &z2)
feSub(&z2, &z3, &z2)
feMul(&x2, &tmp1, &tmp0)
feSub(&tmp1, &tmp1, &tmp0)
feSquare(&z2, &z2)
feMul121666(&z3, &tmp1)
feSquare(&x3, &x3)
feAdd(&tmp0, &tmp0, &z3)
feMul(&z3, &x1, &z2)
feMul(&z2, &tmp1, &tmp0)
}
feCSwap(&x2, &x3, swap)
feCSwap(&z2, &z3, swap)
feInvert(&z2, &z2)
feMul(&x2, &x2, &z2)
feToBytes(out, &x2)
} }

View File

@ -1,828 +0,0 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package curve25519
import "encoding/binary"
// This code is a port of the public domain, "ref10" implementation of
// curve25519 from SUPERCOP 20130419 by D. J. Bernstein.
// fieldElement represents an element of the field GF(2^255 - 19). An element
// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on
// context.
type fieldElement [10]int32
func feZero(fe *fieldElement) {
for i := range fe {
fe[i] = 0
}
}
func feOne(fe *fieldElement) {
feZero(fe)
fe[0] = 1
}
func feAdd(dst, a, b *fieldElement) {
for i := range dst {
dst[i] = a[i] + b[i]
}
}
func feSub(dst, a, b *fieldElement) {
for i := range dst {
dst[i] = a[i] - b[i]
}
}
func feCopy(dst, src *fieldElement) {
for i := range dst {
dst[i] = src[i]
}
}
// feCSwap replaces (f,g) with (g,f) if b == 1; replaces (f,g) with (f,g) if b == 0.
//
// Preconditions: b in {0,1}.
func feCSwap(f, g *fieldElement, b int32) {
b = -b
for i := range f {
t := b & (f[i] ^ g[i])
f[i] ^= t
g[i] ^= t
}
}
// load3 reads a 24-bit, little-endian value from in.
func load3(in []byte) int64 {
var r int64
r = int64(in[0])
r |= int64(in[1]) << 8
r |= int64(in[2]) << 16
return r
}
// load4 reads a 32-bit, little-endian value from in.
func load4(in []byte) int64 {
return int64(binary.LittleEndian.Uint32(in))
}
func feFromBytes(dst *fieldElement, src *[32]byte) {
h0 := load4(src[:])
h1 := load3(src[4:]) << 6
h2 := load3(src[7:]) << 5
h3 := load3(src[10:]) << 3
h4 := load3(src[13:]) << 2
h5 := load4(src[16:])
h6 := load3(src[20:]) << 7
h7 := load3(src[23:]) << 5
h8 := load3(src[26:]) << 4
h9 := (load3(src[29:]) & 0x7fffff) << 2
var carry [10]int64
carry[9] = (h9 + 1<<24) >> 25
h0 += carry[9] * 19
h9 -= carry[9] << 25
carry[1] = (h1 + 1<<24) >> 25
h2 += carry[1]
h1 -= carry[1] << 25
carry[3] = (h3 + 1<<24) >> 25
h4 += carry[3]
h3 -= carry[3] << 25
carry[5] = (h5 + 1<<24) >> 25
h6 += carry[5]
h5 -= carry[5] << 25
carry[7] = (h7 + 1<<24) >> 25
h8 += carry[7]
h7 -= carry[7] << 25
carry[0] = (h0 + 1<<25) >> 26
h1 += carry[0]
h0 -= carry[0] << 26
carry[2] = (h2 + 1<<25) >> 26
h3 += carry[2]
h2 -= carry[2] << 26
carry[4] = (h4 + 1<<25) >> 26
h5 += carry[4]
h4 -= carry[4] << 26
carry[6] = (h6 + 1<<25) >> 26
h7 += carry[6]
h6 -= carry[6] << 26
carry[8] = (h8 + 1<<25) >> 26
h9 += carry[8]
h8 -= carry[8] << 26
dst[0] = int32(h0)
dst[1] = int32(h1)
dst[2] = int32(h2)
dst[3] = int32(h3)
dst[4] = int32(h4)
dst[5] = int32(h5)
dst[6] = int32(h6)
dst[7] = int32(h7)
dst[8] = int32(h8)
dst[9] = int32(h9)
}
// feToBytes marshals h to s.
// Preconditions:
// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
//
// Write p=2^255-19; q=floor(h/p).
// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))).
//
// Proof:
// Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4.
// Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4.
//
// Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9).
// Then 0<y<1.
//
// Write r=h-pq.
// Have 0<=r<=p-1=2^255-20.
// Thus 0<=r+19(2^-255)r<r+19(2^-255)2^255<=2^255-1.
//
// Write x=r+19(2^-255)r+y.
// Then 0<x<2^255 so floor(2^(-255)x) = 0 so floor(q+2^(-255)x) = q.
//
// Have q+2^(-255)x = 2^(-255)(h + 19 2^(-25) h9 + 2^(-1))
// so floor(2^(-255)(h + 19 2^(-25) h9 + 2^(-1))) = q.
func feToBytes(s *[32]byte, h *fieldElement) {
var carry [10]int32
q := (19*h[9] + (1 << 24)) >> 25
q = (h[0] + q) >> 26
q = (h[1] + q) >> 25
q = (h[2] + q) >> 26
q = (h[3] + q) >> 25
q = (h[4] + q) >> 26
q = (h[5] + q) >> 25
q = (h[6] + q) >> 26
q = (h[7] + q) >> 25
q = (h[8] + q) >> 26
q = (h[9] + q) >> 25
// Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20.
h[0] += 19 * q
// Goal: Output h-2^255 q, which is between 0 and 2^255-20.
carry[0] = h[0] >> 26
h[1] += carry[0]
h[0] -= carry[0] << 26
carry[1] = h[1] >> 25
h[2] += carry[1]
h[1] -= carry[1] << 25
carry[2] = h[2] >> 26
h[3] += carry[2]
h[2] -= carry[2] << 26
carry[3] = h[3] >> 25
h[4] += carry[3]
h[3] -= carry[3] << 25
carry[4] = h[4] >> 26
h[5] += carry[4]
h[4] -= carry[4] << 26
carry[5] = h[5] >> 25
h[6] += carry[5]
h[5] -= carry[5] << 25
carry[6] = h[6] >> 26
h[7] += carry[6]
h[6] -= carry[6] << 26
carry[7] = h[7] >> 25
h[8] += carry[7]
h[7] -= carry[7] << 25
carry[8] = h[8] >> 26
h[9] += carry[8]
h[8] -= carry[8] << 26
carry[9] = h[9] >> 25
h[9] -= carry[9] << 25
// h10 = carry9
// Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
// Have h[0]+...+2^230 h[9] between 0 and 2^255-1;
// evidently 2^255 h10-2^255 q = 0.
// Goal: Output h[0]+...+2^230 h[9].
s[0] = byte(h[0] >> 0)
s[1] = byte(h[0] >> 8)
s[2] = byte(h[0] >> 16)
s[3] = byte((h[0] >> 24) | (h[1] << 2))
s[4] = byte(h[1] >> 6)
s[5] = byte(h[1] >> 14)
s[6] = byte((h[1] >> 22) | (h[2] << 3))
s[7] = byte(h[2] >> 5)
s[8] = byte(h[2] >> 13)
s[9] = byte((h[2] >> 21) | (h[3] << 5))
s[10] = byte(h[3] >> 3)
s[11] = byte(h[3] >> 11)
s[12] = byte((h[3] >> 19) | (h[4] << 6))
s[13] = byte(h[4] >> 2)
s[14] = byte(h[4] >> 10)
s[15] = byte(h[4] >> 18)
s[16] = byte(h[5] >> 0)
s[17] = byte(h[5] >> 8)
s[18] = byte(h[5] >> 16)
s[19] = byte((h[5] >> 24) | (h[6] << 1))
s[20] = byte(h[6] >> 7)
s[21] = byte(h[6] >> 15)
s[22] = byte((h[6] >> 23) | (h[7] << 3))
s[23] = byte(h[7] >> 5)
s[24] = byte(h[7] >> 13)
s[25] = byte((h[7] >> 21) | (h[8] << 4))
s[26] = byte(h[8] >> 4)
s[27] = byte(h[8] >> 12)
s[28] = byte((h[8] >> 20) | (h[9] << 6))
s[29] = byte(h[9] >> 2)
s[30] = byte(h[9] >> 10)
s[31] = byte(h[9] >> 18)
}
// feMul calculates h = f * g
// Can overlap h with f or g.
//
// Preconditions:
// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
// |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
//
// Postconditions:
// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
//
// Notes on implementation strategy:
//
// Using schoolbook multiplication.
// Karatsuba would save a little in some cost models.
//
// Most multiplications by 2 and 19 are 32-bit precomputations;
// cheaper than 64-bit postcomputations.
//
// There is one remaining multiplication by 19 in the carry chain;
// one *19 precomputation can be merged into this,
// but the resulting data flow is considerably less clean.
//
// There are 12 carries below.
// 10 of them are 2-way parallelizable and vectorizable.
// Can get away with 11 carries, but then data flow is much deeper.
//
// With tighter constraints on inputs can squeeze carries into int32.
func feMul(h, f, g *fieldElement) {
f0 := f[0]
f1 := f[1]
f2 := f[2]
f3 := f[3]
f4 := f[4]
f5 := f[5]
f6 := f[6]
f7 := f[7]
f8 := f[8]
f9 := f[9]
g0 := g[0]
g1 := g[1]
g2 := g[2]
g3 := g[3]
g4 := g[4]
g5 := g[5]
g6 := g[6]
g7 := g[7]
g8 := g[8]
g9 := g[9]
g1_19 := 19 * g1 // 1.4*2^29
g2_19 := 19 * g2 // 1.4*2^30; still ok
g3_19 := 19 * g3
g4_19 := 19 * g4
g5_19 := 19 * g5
g6_19 := 19 * g6
g7_19 := 19 * g7
g8_19 := 19 * g8
g9_19 := 19 * g9
f1_2 := 2 * f1
f3_2 := 2 * f3
f5_2 := 2 * f5
f7_2 := 2 * f7
f9_2 := 2 * f9
f0g0 := int64(f0) * int64(g0)
f0g1 := int64(f0) * int64(g1)
f0g2 := int64(f0) * int64(g2)
f0g3 := int64(f0) * int64(g3)
f0g4 := int64(f0) * int64(g4)
f0g5 := int64(f0) * int64(g5)
f0g6 := int64(f0) * int64(g6)
f0g7 := int64(f0) * int64(g7)
f0g8 := int64(f0) * int64(g8)
f0g9 := int64(f0) * int64(g9)
f1g0 := int64(f1) * int64(g0)
f1g1_2 := int64(f1_2) * int64(g1)
f1g2 := int64(f1) * int64(g2)
f1g3_2 := int64(f1_2) * int64(g3)
f1g4 := int64(f1) * int64(g4)
f1g5_2 := int64(f1_2) * int64(g5)
f1g6 := int64(f1) * int64(g6)
f1g7_2 := int64(f1_2) * int64(g7)
f1g8 := int64(f1) * int64(g8)
f1g9_38 := int64(f1_2) * int64(g9_19)
f2g0 := int64(f2) * int64(g0)
f2g1 := int64(f2) * int64(g1)
f2g2 := int64(f2) * int64(g2)
f2g3 := int64(f2) * int64(g3)
f2g4 := int64(f2) * int64(g4)
f2g5 := int64(f2) * int64(g5)
f2g6 := int64(f2) * int64(g6)
f2g7 := int64(f2) * int64(g7)
f2g8_19 := int64(f2) * int64(g8_19)
f2g9_19 := int64(f2) * int64(g9_19)
f3g0 := int64(f3) * int64(g0)
f3g1_2 := int64(f3_2) * int64(g1)
f3g2 := int64(f3) * int64(g2)
f3g3_2 := int64(f3_2) * int64(g3)
f3g4 := int64(f3) * int64(g4)
f3g5_2 := int64(f3_2) * int64(g5)
f3g6 := int64(f3) * int64(g6)
f3g7_38 := int64(f3_2) * int64(g7_19)
f3g8_19 := int64(f3) * int64(g8_19)
f3g9_38 := int64(f3_2) * int64(g9_19)
f4g0 := int64(f4) * int64(g0)
f4g1 := int64(f4) * int64(g1)
f4g2 := int64(f4) * int64(g2)
f4g3 := int64(f4) * int64(g3)
f4g4 := int64(f4) * int64(g4)
f4g5 := int64(f4) * int64(g5)
f4g6_19 := int64(f4) * int64(g6_19)
f4g7_19 := int64(f4) * int64(g7_19)
f4g8_19 := int64(f4) * int64(g8_19)
f4g9_19 := int64(f4) * int64(g9_19)
f5g0 := int64(f5) * int64(g0)
f5g1_2 := int64(f5_2) * int64(g1)
f5g2 := int64(f5) * int64(g2)
f5g3_2 := int64(f5_2) * int64(g3)
f5g4 := int64(f5) * int64(g4)
f5g5_38 := int64(f5_2) * int64(g5_19)
f5g6_19 := int64(f5) * int64(g6_19)
f5g7_38 := int64(f5_2) * int64(g7_19)
f5g8_19 := int64(f5) * int64(g8_19)
f5g9_38 := int64(f5_2) * int64(g9_19)
f6g0 := int64(f6) * int64(g0)
f6g1 := int64(f6) * int64(g1)
f6g2 := int64(f6) * int64(g2)
f6g3 := int64(f6) * int64(g3)
f6g4_19 := int64(f6) * int64(g4_19)
f6g5_19 := int64(f6) * int64(g5_19)
f6g6_19 := int64(f6) * int64(g6_19)
f6g7_19 := int64(f6) * int64(g7_19)
f6g8_19 := int64(f6) * int64(g8_19)
f6g9_19 := int64(f6) * int64(g9_19)
f7g0 := int64(f7) * int64(g0)
f7g1_2 := int64(f7_2) * int64(g1)
f7g2 := int64(f7) * int64(g2)
f7g3_38 := int64(f7_2) * int64(g3_19)
f7g4_19 := int64(f7) * int64(g4_19)
f7g5_38 := int64(f7_2) * int64(g5_19)
f7g6_19 := int64(f7) * int64(g6_19)
f7g7_38 := int64(f7_2) * int64(g7_19)
f7g8_19 := int64(f7) * int64(g8_19)
f7g9_38 := int64(f7_2) * int64(g9_19)
f8g0 := int64(f8) * int64(g0)
f8g1 := int64(f8) * int64(g1)
f8g2_19 := int64(f8) * int64(g2_19)
f8g3_19 := int64(f8) * int64(g3_19)
f8g4_19 := int64(f8) * int64(g4_19)
f8g5_19 := int64(f8) * int64(g5_19)
f8g6_19 := int64(f8) * int64(g6_19)
f8g7_19 := int64(f8) * int64(g7_19)
f8g8_19 := int64(f8) * int64(g8_19)
f8g9_19 := int64(f8) * int64(g9_19)
f9g0 := int64(f9) * int64(g0)
f9g1_38 := int64(f9_2) * int64(g1_19)
f9g2_19 := int64(f9) * int64(g2_19)
f9g3_38 := int64(f9_2) * int64(g3_19)
f9g4_19 := int64(f9) * int64(g4_19)
f9g5_38 := int64(f9_2) * int64(g5_19)
f9g6_19 := int64(f9) * int64(g6_19)
f9g7_38 := int64(f9_2) * int64(g7_19)
f9g8_19 := int64(f9) * int64(g8_19)
f9g9_38 := int64(f9_2) * int64(g9_19)
h0 := f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38
h1 := f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19
h2 := f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38
h3 := f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19
h4 := f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38
h5 := f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19
h6 := f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38
h7 := f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19
h8 := f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38
h9 := f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0
var carry [10]int64
// |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38))
// i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8
// |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19))
// i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9
carry[0] = (h0 + (1 << 25)) >> 26
h1 += carry[0]
h0 -= carry[0] << 26
carry[4] = (h4 + (1 << 25)) >> 26
h5 += carry[4]
h4 -= carry[4] << 26
// |h0| <= 2^25
// |h4| <= 2^25
// |h1| <= 1.51*2^58
// |h5| <= 1.51*2^58
carry[1] = (h1 + (1 << 24)) >> 25
h2 += carry[1]
h1 -= carry[1] << 25
carry[5] = (h5 + (1 << 24)) >> 25
h6 += carry[5]
h5 -= carry[5] << 25
// |h1| <= 2^24; from now on fits into int32
// |h5| <= 2^24; from now on fits into int32
// |h2| <= 1.21*2^59
// |h6| <= 1.21*2^59
carry[2] = (h2 + (1 << 25)) >> 26
h3 += carry[2]
h2 -= carry[2] << 26
carry[6] = (h6 + (1 << 25)) >> 26
h7 += carry[6]
h6 -= carry[6] << 26
// |h2| <= 2^25; from now on fits into int32 unchanged
// |h6| <= 2^25; from now on fits into int32 unchanged
// |h3| <= 1.51*2^58
// |h7| <= 1.51*2^58
carry[3] = (h3 + (1 << 24)) >> 25
h4 += carry[3]
h3 -= carry[3] << 25
carry[7] = (h7 + (1 << 24)) >> 25
h8 += carry[7]
h7 -= carry[7] << 25
// |h3| <= 2^24; from now on fits into int32 unchanged
// |h7| <= 2^24; from now on fits into int32 unchanged
// |h4| <= 1.52*2^33
// |h8| <= 1.52*2^33
carry[4] = (h4 + (1 << 25)) >> 26
h5 += carry[4]
h4 -= carry[4] << 26
carry[8] = (h8 + (1 << 25)) >> 26
h9 += carry[8]
h8 -= carry[8] << 26
// |h4| <= 2^25; from now on fits into int32 unchanged
// |h8| <= 2^25; from now on fits into int32 unchanged
// |h5| <= 1.01*2^24
// |h9| <= 1.51*2^58
carry[9] = (h9 + (1 << 24)) >> 25
h0 += carry[9] * 19
h9 -= carry[9] << 25
// |h9| <= 2^24; from now on fits into int32 unchanged
// |h0| <= 1.8*2^37
carry[0] = (h0 + (1 << 25)) >> 26
h1 += carry[0]
h0 -= carry[0] << 26
// |h0| <= 2^25; from now on fits into int32 unchanged
// |h1| <= 1.01*2^24
h[0] = int32(h0)
h[1] = int32(h1)
h[2] = int32(h2)
h[3] = int32(h3)
h[4] = int32(h4)
h[5] = int32(h5)
h[6] = int32(h6)
h[7] = int32(h7)
h[8] = int32(h8)
h[9] = int32(h9)
}
// feSquare calculates h = f*f. Can overlap h with f.
//
// Preconditions:
// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
//
// Postconditions:
// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
func feSquare(h, f *fieldElement) {
f0 := f[0]
f1 := f[1]
f2 := f[2]
f3 := f[3]
f4 := f[4]
f5 := f[5]
f6 := f[6]
f7 := f[7]
f8 := f[8]
f9 := f[9]
f0_2 := 2 * f0
f1_2 := 2 * f1
f2_2 := 2 * f2
f3_2 := 2 * f3
f4_2 := 2 * f4
f5_2 := 2 * f5
f6_2 := 2 * f6
f7_2 := 2 * f7
f5_38 := 38 * f5 // 1.31*2^30
f6_19 := 19 * f6 // 1.31*2^30
f7_38 := 38 * f7 // 1.31*2^30
f8_19 := 19 * f8 // 1.31*2^30
f9_38 := 38 * f9 // 1.31*2^30
f0f0 := int64(f0) * int64(f0)
f0f1_2 := int64(f0_2) * int64(f1)
f0f2_2 := int64(f0_2) * int64(f2)
f0f3_2 := int64(f0_2) * int64(f3)
f0f4_2 := int64(f0_2) * int64(f4)
f0f5_2 := int64(f0_2) * int64(f5)
f0f6_2 := int64(f0_2) * int64(f6)
f0f7_2 := int64(f0_2) * int64(f7)
f0f8_2 := int64(f0_2) * int64(f8)
f0f9_2 := int64(f0_2) * int64(f9)
f1f1_2 := int64(f1_2) * int64(f1)
f1f2_2 := int64(f1_2) * int64(f2)
f1f3_4 := int64(f1_2) * int64(f3_2)
f1f4_2 := int64(f1_2) * int64(f4)
f1f5_4 := int64(f1_2) * int64(f5_2)
f1f6_2 := int64(f1_2) * int64(f6)
f1f7_4 := int64(f1_2) * int64(f7_2)
f1f8_2 := int64(f1_2) * int64(f8)
f1f9_76 := int64(f1_2) * int64(f9_38)
f2f2 := int64(f2) * int64(f2)
f2f3_2 := int64(f2_2) * int64(f3)
f2f4_2 := int64(f2_2) * int64(f4)
f2f5_2 := int64(f2_2) * int64(f5)
f2f6_2 := int64(f2_2) * int64(f6)
f2f7_2 := int64(f2_2) * int64(f7)
f2f8_38 := int64(f2_2) * int64(f8_19)
f2f9_38 := int64(f2) * int64(f9_38)
f3f3_2 := int64(f3_2) * int64(f3)
f3f4_2 := int64(f3_2) * int64(f4)
f3f5_4 := int64(f3_2) * int64(f5_2)
f3f6_2 := int64(f3_2) * int64(f6)
f3f7_76 := int64(f3_2) * int64(f7_38)
f3f8_38 := int64(f3_2) * int64(f8_19)
f3f9_76 := int64(f3_2) * int64(f9_38)
f4f4 := int64(f4) * int64(f4)
f4f5_2 := int64(f4_2) * int64(f5)
f4f6_38 := int64(f4_2) * int64(f6_19)
f4f7_38 := int64(f4) * int64(f7_38)
f4f8_38 := int64(f4_2) * int64(f8_19)
f4f9_38 := int64(f4) * int64(f9_38)
f5f5_38 := int64(f5) * int64(f5_38)
f5f6_38 := int64(f5_2) * int64(f6_19)
f5f7_76 := int64(f5_2) * int64(f7_38)
f5f8_38 := int64(f5_2) * int64(f8_19)
f5f9_76 := int64(f5_2) * int64(f9_38)
f6f6_19 := int64(f6) * int64(f6_19)
f6f7_38 := int64(f6) * int64(f7_38)
f6f8_38 := int64(f6_2) * int64(f8_19)
f6f9_38 := int64(f6) * int64(f9_38)
f7f7_38 := int64(f7) * int64(f7_38)
f7f8_38 := int64(f7_2) * int64(f8_19)
f7f9_76 := int64(f7_2) * int64(f9_38)
f8f8_19 := int64(f8) * int64(f8_19)
f8f9_38 := int64(f8) * int64(f9_38)
f9f9_38 := int64(f9) * int64(f9_38)
h0 := f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38
h1 := f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38
h2 := f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19
h3 := f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38
h4 := f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38
h5 := f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38
h6 := f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19
h7 := f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38
h8 := f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38
h9 := f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2
var carry [10]int64
carry[0] = (h0 + (1 << 25)) >> 26
h1 += carry[0]
h0 -= carry[0] << 26
carry[4] = (h4 + (1 << 25)) >> 26
h5 += carry[4]
h4 -= carry[4] << 26
carry[1] = (h1 + (1 << 24)) >> 25
h2 += carry[1]
h1 -= carry[1] << 25
carry[5] = (h5 + (1 << 24)) >> 25
h6 += carry[5]
h5 -= carry[5] << 25
carry[2] = (h2 + (1 << 25)) >> 26
h3 += carry[2]
h2 -= carry[2] << 26
carry[6] = (h6 + (1 << 25)) >> 26
h7 += carry[6]
h6 -= carry[6] << 26
carry[3] = (h3 + (1 << 24)) >> 25
h4 += carry[3]
h3 -= carry[3] << 25
carry[7] = (h7 + (1 << 24)) >> 25
h8 += carry[7]
h7 -= carry[7] << 25
carry[4] = (h4 + (1 << 25)) >> 26
h5 += carry[4]
h4 -= carry[4] << 26
carry[8] = (h8 + (1 << 25)) >> 26
h9 += carry[8]
h8 -= carry[8] << 26
carry[9] = (h9 + (1 << 24)) >> 25
h0 += carry[9] * 19
h9 -= carry[9] << 25
carry[0] = (h0 + (1 << 25)) >> 26
h1 += carry[0]
h0 -= carry[0] << 26
h[0] = int32(h0)
h[1] = int32(h1)
h[2] = int32(h2)
h[3] = int32(h3)
h[4] = int32(h4)
h[5] = int32(h5)
h[6] = int32(h6)
h[7] = int32(h7)
h[8] = int32(h8)
h[9] = int32(h9)
}
// feMul121666 calculates h = f * 121666. Can overlap h with f.
//
// Preconditions:
// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
//
// Postconditions:
// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
func feMul121666(h, f *fieldElement) {
h0 := int64(f[0]) * 121666
h1 := int64(f[1]) * 121666
h2 := int64(f[2]) * 121666
h3 := int64(f[3]) * 121666
h4 := int64(f[4]) * 121666
h5 := int64(f[5]) * 121666
h6 := int64(f[6]) * 121666
h7 := int64(f[7]) * 121666
h8 := int64(f[8]) * 121666
h9 := int64(f[9]) * 121666
var carry [10]int64
carry[9] = (h9 + (1 << 24)) >> 25
h0 += carry[9] * 19
h9 -= carry[9] << 25
carry[1] = (h1 + (1 << 24)) >> 25
h2 += carry[1]
h1 -= carry[1] << 25
carry[3] = (h3 + (1 << 24)) >> 25
h4 += carry[3]
h3 -= carry[3] << 25
carry[5] = (h5 + (1 << 24)) >> 25
h6 += carry[5]
h5 -= carry[5] << 25
carry[7] = (h7 + (1 << 24)) >> 25
h8 += carry[7]
h7 -= carry[7] << 25
carry[0] = (h0 + (1 << 25)) >> 26
h1 += carry[0]
h0 -= carry[0] << 26
carry[2] = (h2 + (1 << 25)) >> 26
h3 += carry[2]
h2 -= carry[2] << 26
carry[4] = (h4 + (1 << 25)) >> 26
h5 += carry[4]
h4 -= carry[4] << 26
carry[6] = (h6 + (1 << 25)) >> 26
h7 += carry[6]
h6 -= carry[6] << 26
carry[8] = (h8 + (1 << 25)) >> 26
h9 += carry[8]
h8 -= carry[8] << 26
h[0] = int32(h0)
h[1] = int32(h1)
h[2] = int32(h2)
h[3] = int32(h3)
h[4] = int32(h4)
h[5] = int32(h5)
h[6] = int32(h6)
h[7] = int32(h7)
h[8] = int32(h8)
h[9] = int32(h9)
}
// feInvert sets out = z^-1.
func feInvert(out, z *fieldElement) {
var t0, t1, t2, t3 fieldElement
var i int
feSquare(&t0, z)
for i = 1; i < 1; i++ {
feSquare(&t0, &t0)
}
feSquare(&t1, &t0)
for i = 1; i < 2; i++ {
feSquare(&t1, &t1)
}
feMul(&t1, z, &t1)
feMul(&t0, &t0, &t1)
feSquare(&t2, &t0)
for i = 1; i < 1; i++ {
feSquare(&t2, &t2)
}
feMul(&t1, &t1, &t2)
feSquare(&t2, &t1)
for i = 1; i < 5; i++ {
feSquare(&t2, &t2)
}
feMul(&t1, &t2, &t1)
feSquare(&t2, &t1)
for i = 1; i < 10; i++ {
feSquare(&t2, &t2)
}
feMul(&t2, &t2, &t1)
feSquare(&t3, &t2)
for i = 1; i < 20; i++ {
feSquare(&t3, &t3)
}
feMul(&t2, &t3, &t2)
feSquare(&t2, &t2)
for i = 1; i < 10; i++ {
feSquare(&t2, &t2)
}
feMul(&t1, &t2, &t1)
feSquare(&t2, &t1)
for i = 1; i < 50; i++ {
feSquare(&t2, &t2)
}
feMul(&t2, &t2, &t1)
feSquare(&t3, &t2)
for i = 1; i < 100; i++ {
feSquare(&t3, &t3)
}
feMul(&t2, &t3, &t2)
feSquare(&t2, &t2)
for i = 1; i < 50; i++ {
feSquare(&t2, &t2)
}
feMul(&t1, &t2, &t1)
feSquare(&t1, &t1)
for i = 1; i < 5; i++ {
feSquare(&t1, &t1)
}
feMul(out, &t1, &t0)
}
func scalarMultGeneric(out, in, base *[32]byte) {
var e [32]byte
copy(e[:], in[:])
e[0] &= 248
e[31] &= 127
e[31] |= 64
var x1, x2, z2, x3, z3, tmp0, tmp1 fieldElement
feFromBytes(&x1, base)
feOne(&x2)
feCopy(&x3, &x1)
feOne(&z3)
swap := int32(0)
for pos := 254; pos >= 0; pos-- {
b := e[pos/8] >> uint(pos&7)
b &= 1
swap ^= int32(b)
feCSwap(&x2, &x3, swap)
feCSwap(&z2, &z3, swap)
swap = int32(b)
feSub(&tmp0, &x3, &z3)
feSub(&tmp1, &x2, &z2)
feAdd(&x2, &x2, &z2)
feAdd(&z2, &x3, &z3)
feMul(&z3, &tmp0, &x2)
feMul(&z2, &z2, &tmp1)
feSquare(&tmp0, &tmp1)
feSquare(&tmp1, &x2)
feAdd(&x3, &z3, &z2)
feSub(&z2, &z3, &z2)
feMul(&x2, &tmp1, &tmp0)
feSub(&tmp1, &tmp1, &tmp0)
feSquare(&z2, &z2)
feMul121666(&z3, &tmp1)
feSquare(&x3, &x3)
feAdd(&tmp0, &tmp0, &z3)
feMul(&z3, &x1, &z2)
feMul(&z2, &tmp1, &tmp0)
}
feCSwap(&x2, &x3, swap)
feCSwap(&z2, &z3, swap)
feInvert(&z2, &z2)
feMul(&x2, &x2, &z2)
feToBytes(out, &x2)
}

View File

@ -1,11 +0,0 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !amd64 gccgo appengine purego
package curve25519
func scalarMult(out, in, base *[32]byte) {
scalarMultGeneric(out, in, base)
}

23
vendor/golang.org/x/crypto/curve25519/doc.go generated vendored Normal file
View File

@ -0,0 +1,23 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package curve25519 provides an implementation of scalar multiplication on
// the elliptic curve known as curve25519. See https://cr.yp.to/ecdh.html
package curve25519 // import "golang.org/x/crypto/curve25519"
// basePoint is the x coordinate of the generator of the curve.
var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
// ScalarMult sets dst to the product in*base where dst and base are the x
// coordinates of group points and all values are in little-endian form.
func ScalarMult(dst, in, base *[32]byte) {
scalarMult(dst, in, base)
}
// ScalarBaseMult sets dst to the product in*base where dst and base are the x
// coordinates of group points, base is the standard generator and all values
// are in little-endian form.
func ScalarBaseMult(dst, in *[32]byte) {
ScalarMult(dst, in, &basePoint)
}

73
vendor/golang.org/x/crypto/curve25519/freeze_amd64.s generated vendored Normal file
View File

@ -0,0 +1,73 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This code was translated into a form compatible with 6a from the public
// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
// +build amd64,!gccgo,!appengine
#include "const_amd64.h"
// func freeze(inout *[5]uint64)
TEXT ·freeze(SB),7,$0-8
MOVQ inout+0(FP), DI
MOVQ 0(DI),SI
MOVQ 8(DI),DX
MOVQ 16(DI),CX
MOVQ 24(DI),R8
MOVQ 32(DI),R9
MOVQ $REDMASK51,AX
MOVQ AX,R10
SUBQ $18,R10
MOVQ $3,R11
REDUCELOOP:
MOVQ SI,R12
SHRQ $51,R12
ANDQ AX,SI
ADDQ R12,DX
MOVQ DX,R12
SHRQ $51,R12
ANDQ AX,DX
ADDQ R12,CX
MOVQ CX,R12
SHRQ $51,R12
ANDQ AX,CX
ADDQ R12,R8
MOVQ R8,R12
SHRQ $51,R12
ANDQ AX,R8
ADDQ R12,R9
MOVQ R9,R12
SHRQ $51,R12
ANDQ AX,R9
IMUL3Q $19,R12,R12
ADDQ R12,SI
SUBQ $1,R11
JA REDUCELOOP
MOVQ $1,R12
CMPQ R10,SI
CMOVQLT R11,R12
CMPQ AX,DX
CMOVQNE R11,R12
CMPQ AX,CX
CMOVQNE R11,R12
CMPQ AX,R8
CMOVQNE R11,R12
CMPQ AX,R9
CMOVQNE R11,R12
NEGQ R12
ANDQ R12,AX
ANDQ R12,R10
SUBQ R10,SI
SUBQ AX,DX
SUBQ AX,CX
SUBQ AX,R8
SUBQ AX,R9
MOVQ SI,0(DI)
MOVQ DX,8(DI)
MOVQ CX,16(DI)
MOVQ R8,24(DI)
MOVQ R9,32(DI)
RET

View File

@ -5,84 +5,9 @@
// This code was translated into a form compatible with 6a from the public // This code was translated into a form compatible with 6a from the public
// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html // domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
// +build amd64,!gccgo,!appengine,!purego // +build amd64,!gccgo,!appengine
#define REDMASK51 0x0007FFFFFFFFFFFF #include "const_amd64.h"
// These constants cannot be encoded in non-MOVQ immediates.
// We access them directly from memory instead.
DATA ·_121666_213(SB)/8, $996687872
GLOBL ·_121666_213(SB), 8, $8
DATA ·_2P0(SB)/8, $0xFFFFFFFFFFFDA
GLOBL ·_2P0(SB), 8, $8
DATA ·_2P1234(SB)/8, $0xFFFFFFFFFFFFE
GLOBL ·_2P1234(SB), 8, $8
// func freeze(inout *[5]uint64)
TEXT ·freeze(SB),7,$0-8
MOVQ inout+0(FP), DI
MOVQ 0(DI),SI
MOVQ 8(DI),DX
MOVQ 16(DI),CX
MOVQ 24(DI),R8
MOVQ 32(DI),R9
MOVQ $REDMASK51,AX
MOVQ AX,R10
SUBQ $18,R10
MOVQ $3,R11
REDUCELOOP:
MOVQ SI,R12
SHRQ $51,R12
ANDQ AX,SI
ADDQ R12,DX
MOVQ DX,R12
SHRQ $51,R12
ANDQ AX,DX
ADDQ R12,CX
MOVQ CX,R12
SHRQ $51,R12
ANDQ AX,CX
ADDQ R12,R8
MOVQ R8,R12
SHRQ $51,R12
ANDQ AX,R8
ADDQ R12,R9
MOVQ R9,R12
SHRQ $51,R12
ANDQ AX,R9
IMUL3Q $19,R12,R12
ADDQ R12,SI
SUBQ $1,R11
JA REDUCELOOP
MOVQ $1,R12
CMPQ R10,SI
CMOVQLT R11,R12
CMPQ AX,DX
CMOVQNE R11,R12
CMPQ AX,CX
CMOVQNE R11,R12
CMPQ AX,R8
CMOVQNE R11,R12
CMPQ AX,R9
CMOVQNE R11,R12
NEGQ R12
ANDQ R12,AX
ANDQ R12,R10
SUBQ R10,SI
SUBQ AX,DX
SUBQ AX,CX
SUBQ AX,R8
SUBQ AX,R9
MOVQ SI,0(DI)
MOVQ DX,8(DI)
MOVQ CX,16(DI)
MOVQ R8,24(DI)
MOVQ R9,32(DI)
RET
// func ladderstep(inout *[5][5]uint64) // func ladderstep(inout *[5][5]uint64)
TEXT ·ladderstep(SB),0,$296-8 TEXT ·ladderstep(SB),0,$296-8
@ -196,18 +121,18 @@ TEXT ·ladderstep(SB),0,$296-8
ADDQ AX,R12 ADDQ AX,R12
ADCQ DX,R13 ADCQ DX,R13
MOVQ $REDMASK51,DX MOVQ $REDMASK51,DX
SHLQ $13,SI,CX SHLQ $13,CX:SI
ANDQ DX,SI ANDQ DX,SI
SHLQ $13,R8,R9 SHLQ $13,R9:R8
ANDQ DX,R8 ANDQ DX,R8
ADDQ CX,R8 ADDQ CX,R8
SHLQ $13,R10,R11 SHLQ $13,R11:R10
ANDQ DX,R10 ANDQ DX,R10
ADDQ R9,R10 ADDQ R9,R10
SHLQ $13,R12,R13 SHLQ $13,R13:R12
ANDQ DX,R12 ANDQ DX,R12
ADDQ R11,R12 ADDQ R11,R12
SHLQ $13,R14,R15 SHLQ $13,R15:R14
ANDQ DX,R14 ANDQ DX,R14
ADDQ R13,R14 ADDQ R13,R14
IMUL3Q $19,R15,CX IMUL3Q $19,R15,CX
@ -311,18 +236,18 @@ TEXT ·ladderstep(SB),0,$296-8
ADDQ AX,R12 ADDQ AX,R12
ADCQ DX,R13 ADCQ DX,R13
MOVQ $REDMASK51,DX MOVQ $REDMASK51,DX
SHLQ $13,SI,CX SHLQ $13,CX:SI
ANDQ DX,SI ANDQ DX,SI
SHLQ $13,R8,R9 SHLQ $13,R9:R8
ANDQ DX,R8 ANDQ DX,R8
ADDQ CX,R8 ADDQ CX,R8
SHLQ $13,R10,R11 SHLQ $13,R11:R10
ANDQ DX,R10 ANDQ DX,R10
ADDQ R9,R10 ADDQ R9,R10
SHLQ $13,R12,R13 SHLQ $13,R13:R12
ANDQ DX,R12 ANDQ DX,R12
ADDQ R11,R12 ADDQ R11,R12
SHLQ $13,R14,R15 SHLQ $13,R15:R14
ANDQ DX,R14 ANDQ DX,R14
ADDQ R13,R14 ADDQ R13,R14
IMUL3Q $19,R15,CX IMUL3Q $19,R15,CX
@ -516,18 +441,18 @@ TEXT ·ladderstep(SB),0,$296-8
ADDQ AX,R12 ADDQ AX,R12
ADCQ DX,R13 ADCQ DX,R13
MOVQ $REDMASK51,DX MOVQ $REDMASK51,DX
SHLQ $13,SI,CX SHLQ $13,CX:SI
ANDQ DX,SI ANDQ DX,SI
SHLQ $13,R8,R9 SHLQ $13,R9:R8
ANDQ DX,R8 ANDQ DX,R8
ADDQ CX,R8 ADDQ CX,R8
SHLQ $13,R10,R11 SHLQ $13,R11:R10
ANDQ DX,R10 ANDQ DX,R10
ADDQ R9,R10 ADDQ R9,R10
SHLQ $13,R12,R13 SHLQ $13,R13:R12
ANDQ DX,R12 ANDQ DX,R12
ADDQ R11,R12 ADDQ R11,R12
SHLQ $13,R14,R15 SHLQ $13,R15:R14
ANDQ DX,R14 ANDQ DX,R14
ADDQ R13,R14 ADDQ R13,R14
IMUL3Q $19,R15,CX IMUL3Q $19,R15,CX
@ -666,18 +591,18 @@ TEXT ·ladderstep(SB),0,$296-8
ADDQ AX,R12 ADDQ AX,R12
ADCQ DX,R13 ADCQ DX,R13
MOVQ $REDMASK51,DX MOVQ $REDMASK51,DX
SHLQ $13,SI,CX SHLQ $13,CX:SI
ANDQ DX,SI ANDQ DX,SI
SHLQ $13,R8,R9 SHLQ $13,R9:R8
ANDQ DX,R8 ANDQ DX,R8
ADDQ CX,R8 ADDQ CX,R8
SHLQ $13,R10,R11 SHLQ $13,R11:R10
ANDQ DX,R10 ANDQ DX,R10
ADDQ R9,R10 ADDQ R9,R10
SHLQ $13,R12,R13 SHLQ $13,R13:R12
ANDQ DX,R12 ANDQ DX,R12
ADDQ R11,R12 ADDQ R11,R12
SHLQ $13,R14,R15 SHLQ $13,R15:R14
ANDQ DX,R14 ANDQ DX,R14
ADDQ R13,R14 ADDQ R13,R14
IMUL3Q $19,R15,CX IMUL3Q $19,R15,CX
@ -806,18 +731,18 @@ TEXT ·ladderstep(SB),0,$296-8
ADDQ AX,R12 ADDQ AX,R12
ADCQ DX,R13 ADCQ DX,R13
MOVQ $REDMASK51,DX MOVQ $REDMASK51,DX
SHLQ $13,SI,CX SHLQ $13,CX:SI
ANDQ DX,SI ANDQ DX,SI
SHLQ $13,R8,R9 SHLQ $13,R9:R8
ANDQ DX,R8 ANDQ DX,R8
ADDQ CX,R8 ADDQ CX,R8
SHLQ $13,R10,R11 SHLQ $13,R11:R10
ANDQ DX,R10 ANDQ DX,R10
ADDQ R9,R10 ADDQ R9,R10
SHLQ $13,R12,R13 SHLQ $13,R13:R12
ANDQ DX,R12 ANDQ DX,R12
ADDQ R11,R12 ADDQ R11,R12
SHLQ $13,R14,R15 SHLQ $13,R15:R14
ANDQ DX,R14 ANDQ DX,R14
ADDQ R13,R14 ADDQ R13,R14
IMUL3Q $19,R15,CX IMUL3Q $19,R15,CX
@ -921,18 +846,18 @@ TEXT ·ladderstep(SB),0,$296-8
ADDQ AX,R12 ADDQ AX,R12
ADCQ DX,R13 ADCQ DX,R13
MOVQ $REDMASK51,DX MOVQ $REDMASK51,DX
SHLQ $13,SI,CX SHLQ $13,CX:SI
ANDQ DX,SI ANDQ DX,SI
SHLQ $13,R8,R9 SHLQ $13,R9:R8
ANDQ DX,R8 ANDQ DX,R8
ADDQ CX,R8 ADDQ CX,R8
SHLQ $13,R10,R11 SHLQ $13,R11:R10
ANDQ DX,R10 ANDQ DX,R10
ADDQ R9,R10 ADDQ R9,R10
SHLQ $13,R12,R13 SHLQ $13,R13:R12
ANDQ DX,R12 ANDQ DX,R12
ADDQ R11,R12 ADDQ R11,R12
SHLQ $13,R14,R15 SHLQ $13,R15:R14
ANDQ DX,R14 ANDQ DX,R14
ADDQ R13,R14 ADDQ R13,R14
IMUL3Q $19,R15,CX IMUL3Q $19,R15,CX
@ -1071,18 +996,18 @@ TEXT ·ladderstep(SB),0,$296-8
ADDQ AX,R12 ADDQ AX,R12
ADCQ DX,R13 ADCQ DX,R13
MOVQ $REDMASK51,DX MOVQ $REDMASK51,DX
SHLQ $13,SI,CX SHLQ $13,CX:SI
ANDQ DX,SI ANDQ DX,SI
SHLQ $13,R8,R9 SHLQ $13,R9:R8
ANDQ DX,R8 ANDQ DX,R8
ADDQ CX,R8 ADDQ CX,R8
SHLQ $13,R10,R11 SHLQ $13,R11:R10
ANDQ DX,R10 ANDQ DX,R10
ADDQ R9,R10 ADDQ R9,R10
SHLQ $13,R12,R13 SHLQ $13,R13:R12
ANDQ DX,R12 ANDQ DX,R12
ADDQ R11,R12 ADDQ R11,R12
SHLQ $13,R14,R15 SHLQ $13,R15:R14
ANDQ DX,R14 ANDQ DX,R14
ADDQ R13,R14 ADDQ R13,R14
IMUL3Q $19,R15,CX IMUL3Q $19,R15,CX
@ -1221,18 +1146,18 @@ TEXT ·ladderstep(SB),0,$296-8
ADDQ AX,R12 ADDQ AX,R12
ADCQ DX,R13 ADCQ DX,R13
MOVQ $REDMASK51,DX MOVQ $REDMASK51,DX
SHLQ $13,SI,CX SHLQ $13,CX:SI
ANDQ DX,SI ANDQ DX,SI
SHLQ $13,R8,R9 SHLQ $13,R9:R8
ANDQ DX,R8 ANDQ DX,R8
ADDQ CX,R8 ADDQ CX,R8
SHLQ $13,R10,R11 SHLQ $13,R11:R10
ANDQ DX,R10 ANDQ DX,R10
ADDQ R9,R10 ADDQ R9,R10
SHLQ $13,R12,R13 SHLQ $13,R13:R12
ANDQ DX,R12 ANDQ DX,R12
ADDQ R11,R12 ADDQ R11,R12
SHLQ $13,R14,R15 SHLQ $13,R15:R14
ANDQ DX,R14 ANDQ DX,R14
ADDQ R13,R14 ADDQ R13,R14
IMUL3Q $19,R15,CX IMUL3Q $19,R15,CX
@ -1407,18 +1332,18 @@ TEXT ·ladderstep(SB),0,$296-8
ADDQ AX,R12 ADDQ AX,R12
ADCQ DX,R13 ADCQ DX,R13
MOVQ $REDMASK51,DX MOVQ $REDMASK51,DX
SHLQ $13,SI,CX SHLQ $13,CX:SI
ANDQ DX,SI ANDQ DX,SI
SHLQ $13,R8,R9 SHLQ $13,R9:R8
ANDQ DX,R8 ANDQ DX,R8
ADDQ CX,R8 ADDQ CX,R8
SHLQ $13,R10,R11 SHLQ $13,R11:R10
ANDQ DX,R10 ANDQ DX,R10
ADDQ R9,R10 ADDQ R9,R10
SHLQ $13,R12,R13 SHLQ $13,R13:R12
ANDQ DX,R12 ANDQ DX,R12
ADDQ R11,R12 ADDQ R11,R12
SHLQ $13,R14,R15 SHLQ $13,R15:R14
ANDQ DX,R14 ANDQ DX,R14
ADDQ R13,R14 ADDQ R13,R14
IMUL3Q $19,R15,CX IMUL3Q $19,R15,CX
@ -1450,344 +1375,3 @@ TEXT ·ladderstep(SB),0,$296-8
MOVQ AX,104(DI) MOVQ AX,104(DI)
MOVQ R10,112(DI) MOVQ R10,112(DI)
RET RET
// func cswap(inout *[4][5]uint64, v uint64)
TEXT ·cswap(SB),7,$0
MOVQ inout+0(FP),DI
MOVQ v+8(FP),SI
SUBQ $1, SI
NOTQ SI
MOVQ SI, X15
PSHUFD $0x44, X15, X15
MOVOU 0(DI), X0
MOVOU 16(DI), X2
MOVOU 32(DI), X4
MOVOU 48(DI), X6
MOVOU 64(DI), X8
MOVOU 80(DI), X1
MOVOU 96(DI), X3
MOVOU 112(DI), X5
MOVOU 128(DI), X7
MOVOU 144(DI), X9
MOVO X1, X10
MOVO X3, X11
MOVO X5, X12
MOVO X7, X13
MOVO X9, X14
PXOR X0, X10
PXOR X2, X11
PXOR X4, X12
PXOR X6, X13
PXOR X8, X14
PAND X15, X10
PAND X15, X11
PAND X15, X12
PAND X15, X13
PAND X15, X14
PXOR X10, X0
PXOR X10, X1
PXOR X11, X2
PXOR X11, X3
PXOR X12, X4
PXOR X12, X5
PXOR X13, X6
PXOR X13, X7
PXOR X14, X8
PXOR X14, X9
MOVOU X0, 0(DI)
MOVOU X2, 16(DI)
MOVOU X4, 32(DI)
MOVOU X6, 48(DI)
MOVOU X8, 64(DI)
MOVOU X1, 80(DI)
MOVOU X3, 96(DI)
MOVOU X5, 112(DI)
MOVOU X7, 128(DI)
MOVOU X9, 144(DI)
RET
// func mul(dest, a, b *[5]uint64)
TEXT ·mul(SB),0,$16-24
MOVQ dest+0(FP), DI
MOVQ a+8(FP), SI
MOVQ b+16(FP), DX
MOVQ DX,CX
MOVQ 24(SI),DX
IMUL3Q $19,DX,AX
MOVQ AX,0(SP)
MULQ 16(CX)
MOVQ AX,R8
MOVQ DX,R9
MOVQ 32(SI),DX
IMUL3Q $19,DX,AX
MOVQ AX,8(SP)
MULQ 8(CX)
ADDQ AX,R8
ADCQ DX,R9
MOVQ 0(SI),AX
MULQ 0(CX)
ADDQ AX,R8
ADCQ DX,R9
MOVQ 0(SI),AX
MULQ 8(CX)
MOVQ AX,R10
MOVQ DX,R11
MOVQ 0(SI),AX
MULQ 16(CX)
MOVQ AX,R12
MOVQ DX,R13
MOVQ 0(SI),AX
MULQ 24(CX)
MOVQ AX,R14
MOVQ DX,R15
MOVQ 0(SI),AX
MULQ 32(CX)
MOVQ AX,BX
MOVQ DX,BP
MOVQ 8(SI),AX
MULQ 0(CX)
ADDQ AX,R10
ADCQ DX,R11
MOVQ 8(SI),AX
MULQ 8(CX)
ADDQ AX,R12
ADCQ DX,R13
MOVQ 8(SI),AX
MULQ 16(CX)
ADDQ AX,R14
ADCQ DX,R15
MOVQ 8(SI),AX
MULQ 24(CX)
ADDQ AX,BX
ADCQ DX,BP
MOVQ 8(SI),DX
IMUL3Q $19,DX,AX
MULQ 32(CX)
ADDQ AX,R8
ADCQ DX,R9
MOVQ 16(SI),AX
MULQ 0(CX)
ADDQ AX,R12
ADCQ DX,R13
MOVQ 16(SI),AX
MULQ 8(CX)
ADDQ AX,R14
ADCQ DX,R15
MOVQ 16(SI),AX
MULQ 16(CX)
ADDQ AX,BX
ADCQ DX,BP
MOVQ 16(SI),DX
IMUL3Q $19,DX,AX
MULQ 24(CX)
ADDQ AX,R8
ADCQ DX,R9
MOVQ 16(SI),DX
IMUL3Q $19,DX,AX
MULQ 32(CX)
ADDQ AX,R10
ADCQ DX,R11
MOVQ 24(SI),AX
MULQ 0(CX)
ADDQ AX,R14
ADCQ DX,R15
MOVQ 24(SI),AX
MULQ 8(CX)
ADDQ AX,BX
ADCQ DX,BP
MOVQ 0(SP),AX
MULQ 24(CX)
ADDQ AX,R10
ADCQ DX,R11
MOVQ 0(SP),AX
MULQ 32(CX)
ADDQ AX,R12
ADCQ DX,R13
MOVQ 32(SI),AX
MULQ 0(CX)
ADDQ AX,BX
ADCQ DX,BP
MOVQ 8(SP),AX
MULQ 16(CX)
ADDQ AX,R10
ADCQ DX,R11
MOVQ 8(SP),AX
MULQ 24(CX)
ADDQ AX,R12
ADCQ DX,R13
MOVQ 8(SP),AX
MULQ 32(CX)
ADDQ AX,R14
ADCQ DX,R15
MOVQ $REDMASK51,SI
SHLQ $13,R8,R9
ANDQ SI,R8
SHLQ $13,R10,R11
ANDQ SI,R10
ADDQ R9,R10
SHLQ $13,R12,R13
ANDQ SI,R12
ADDQ R11,R12
SHLQ $13,R14,R15
ANDQ SI,R14
ADDQ R13,R14
SHLQ $13,BX,BP
ANDQ SI,BX
ADDQ R15,BX
IMUL3Q $19,BP,DX
ADDQ DX,R8
MOVQ R8,DX
SHRQ $51,DX
ADDQ R10,DX
MOVQ DX,CX
SHRQ $51,DX
ANDQ SI,R8
ADDQ R12,DX
MOVQ DX,R9
SHRQ $51,DX
ANDQ SI,CX
ADDQ R14,DX
MOVQ DX,AX
SHRQ $51,DX
ANDQ SI,R9
ADDQ BX,DX
MOVQ DX,R10
SHRQ $51,DX
ANDQ SI,AX
IMUL3Q $19,DX,DX
ADDQ DX,R8
ANDQ SI,R10
MOVQ R8,0(DI)
MOVQ CX,8(DI)
MOVQ R9,16(DI)
MOVQ AX,24(DI)
MOVQ R10,32(DI)
RET
// func square(out, in *[5]uint64)
TEXT ·square(SB),7,$0-16
MOVQ out+0(FP), DI
MOVQ in+8(FP), SI
MOVQ 0(SI),AX
MULQ 0(SI)
MOVQ AX,CX
MOVQ DX,R8
MOVQ 0(SI),AX
SHLQ $1,AX
MULQ 8(SI)
MOVQ AX,R9
MOVQ DX,R10
MOVQ 0(SI),AX
SHLQ $1,AX
MULQ 16(SI)
MOVQ AX,R11
MOVQ DX,R12
MOVQ 0(SI),AX
SHLQ $1,AX
MULQ 24(SI)
MOVQ AX,R13
MOVQ DX,R14
MOVQ 0(SI),AX
SHLQ $1,AX
MULQ 32(SI)
MOVQ AX,R15
MOVQ DX,BX
MOVQ 8(SI),AX
MULQ 8(SI)
ADDQ AX,R11
ADCQ DX,R12
MOVQ 8(SI),AX
SHLQ $1,AX
MULQ 16(SI)
ADDQ AX,R13
ADCQ DX,R14
MOVQ 8(SI),AX
SHLQ $1,AX
MULQ 24(SI)
ADDQ AX,R15
ADCQ DX,BX
MOVQ 8(SI),DX
IMUL3Q $38,DX,AX
MULQ 32(SI)
ADDQ AX,CX
ADCQ DX,R8
MOVQ 16(SI),AX
MULQ 16(SI)
ADDQ AX,R15
ADCQ DX,BX
MOVQ 16(SI),DX
IMUL3Q $38,DX,AX
MULQ 24(SI)
ADDQ AX,CX
ADCQ DX,R8
MOVQ 16(SI),DX
IMUL3Q $38,DX,AX
MULQ 32(SI)
ADDQ AX,R9
ADCQ DX,R10
MOVQ 24(SI),DX
IMUL3Q $19,DX,AX
MULQ 24(SI)
ADDQ AX,R9
ADCQ DX,R10
MOVQ 24(SI),DX
IMUL3Q $38,DX,AX
MULQ 32(SI)
ADDQ AX,R11
ADCQ DX,R12
MOVQ 32(SI),DX
IMUL3Q $19,DX,AX
MULQ 32(SI)
ADDQ AX,R13
ADCQ DX,R14
MOVQ $REDMASK51,SI
SHLQ $13,CX,R8
ANDQ SI,CX
SHLQ $13,R9,R10
ANDQ SI,R9
ADDQ R8,R9
SHLQ $13,R11,R12
ANDQ SI,R11
ADDQ R10,R11
SHLQ $13,R13,R14
ANDQ SI,R13
ADDQ R12,R13
SHLQ $13,R15,BX
ANDQ SI,R15
ADDQ R14,R15
IMUL3Q $19,BX,DX
ADDQ DX,CX
MOVQ CX,DX
SHRQ $51,DX
ADDQ R9,DX
ANDQ SI,CX
MOVQ DX,R8
SHRQ $51,DX
ADDQ R11,DX
ANDQ SI,R8
MOVQ DX,R9
SHRQ $51,DX
ADDQ R13,DX
ANDQ SI,R9
MOVQ DX,AX
SHRQ $51,DX
ADDQ R15,DX
ANDQ SI,AX
MOVQ DX,R10
SHRQ $51,DX
IMUL3Q $19,DX,DX
ADDQ DX,CX
ANDQ SI,R10
MOVQ CX,0(DI)
MOVQ R8,8(DI)
MOVQ R9,16(DI)
MOVQ AX,24(DI)
MOVQ R10,32(DI)
RET

View File

@ -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 amd64,!gccgo,!appengine,!purego // +build amd64,!gccgo,!appengine
package curve25519 package curve25519

169
vendor/golang.org/x/crypto/curve25519/mul_amd64.s generated vendored Normal file
View File

@ -0,0 +1,169 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This code was translated into a form compatible with 6a from the public
// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
// +build amd64,!gccgo,!appengine
#include "const_amd64.h"
// func mul(dest, a, b *[5]uint64)
TEXT ·mul(SB),0,$16-24
MOVQ dest+0(FP), DI
MOVQ a+8(FP), SI
MOVQ b+16(FP), DX
MOVQ DX,CX
MOVQ 24(SI),DX
IMUL3Q $19,DX,AX
MOVQ AX,0(SP)
MULQ 16(CX)
MOVQ AX,R8
MOVQ DX,R9
MOVQ 32(SI),DX
IMUL3Q $19,DX,AX
MOVQ AX,8(SP)
MULQ 8(CX)
ADDQ AX,R8
ADCQ DX,R9
MOVQ 0(SI),AX
MULQ 0(CX)
ADDQ AX,R8
ADCQ DX,R9
MOVQ 0(SI),AX
MULQ 8(CX)
MOVQ AX,R10
MOVQ DX,R11
MOVQ 0(SI),AX
MULQ 16(CX)
MOVQ AX,R12
MOVQ DX,R13
MOVQ 0(SI),AX
MULQ 24(CX)
MOVQ AX,R14
MOVQ DX,R15
MOVQ 0(SI),AX
MULQ 32(CX)
MOVQ AX,BX
MOVQ DX,BP
MOVQ 8(SI),AX
MULQ 0(CX)
ADDQ AX,R10
ADCQ DX,R11
MOVQ 8(SI),AX
MULQ 8(CX)
ADDQ AX,R12
ADCQ DX,R13
MOVQ 8(SI),AX
MULQ 16(CX)
ADDQ AX,R14
ADCQ DX,R15
MOVQ 8(SI),AX
MULQ 24(CX)
ADDQ AX,BX
ADCQ DX,BP
MOVQ 8(SI),DX
IMUL3Q $19,DX,AX
MULQ 32(CX)
ADDQ AX,R8
ADCQ DX,R9
MOVQ 16(SI),AX
MULQ 0(CX)
ADDQ AX,R12
ADCQ DX,R13
MOVQ 16(SI),AX
MULQ 8(CX)
ADDQ AX,R14
ADCQ DX,R15
MOVQ 16(SI),AX
MULQ 16(CX)
ADDQ AX,BX
ADCQ DX,BP
MOVQ 16(SI),DX
IMUL3Q $19,DX,AX
MULQ 24(CX)
ADDQ AX,R8
ADCQ DX,R9
MOVQ 16(SI),DX
IMUL3Q $19,DX,AX
MULQ 32(CX)
ADDQ AX,R10
ADCQ DX,R11
MOVQ 24(SI),AX
MULQ 0(CX)
ADDQ AX,R14
ADCQ DX,R15
MOVQ 24(SI),AX
MULQ 8(CX)
ADDQ AX,BX
ADCQ DX,BP
MOVQ 0(SP),AX
MULQ 24(CX)
ADDQ AX,R10
ADCQ DX,R11
MOVQ 0(SP),AX
MULQ 32(CX)
ADDQ AX,R12
ADCQ DX,R13
MOVQ 32(SI),AX
MULQ 0(CX)
ADDQ AX,BX
ADCQ DX,BP
MOVQ 8(SP),AX
MULQ 16(CX)
ADDQ AX,R10
ADCQ DX,R11
MOVQ 8(SP),AX
MULQ 24(CX)
ADDQ AX,R12
ADCQ DX,R13
MOVQ 8(SP),AX
MULQ 32(CX)
ADDQ AX,R14
ADCQ DX,R15
MOVQ $REDMASK51,SI
SHLQ $13,R9:R8
ANDQ SI,R8
SHLQ $13,R11:R10
ANDQ SI,R10
ADDQ R9,R10
SHLQ $13,R13:R12
ANDQ SI,R12
ADDQ R11,R12
SHLQ $13,R15:R14
ANDQ SI,R14
ADDQ R13,R14
SHLQ $13,BP:BX
ANDQ SI,BX
ADDQ R15,BX
IMUL3Q $19,BP,DX
ADDQ DX,R8
MOVQ R8,DX
SHRQ $51,DX
ADDQ R10,DX
MOVQ DX,CX
SHRQ $51,DX
ANDQ SI,R8
ADDQ R12,DX
MOVQ DX,R9
SHRQ $51,DX
ANDQ SI,CX
ADDQ R14,DX
MOVQ DX,AX
SHRQ $51,DX
ANDQ SI,R9
ADDQ BX,DX
MOVQ DX,R10
SHRQ $51,DX
ANDQ SI,AX
IMUL3Q $19,DX,DX
ADDQ DX,R8
ANDQ SI,R10
MOVQ R8,0(DI)
MOVQ CX,8(DI)
MOVQ R9,16(DI)
MOVQ AX,24(DI)
MOVQ R10,32(DI)
RET

132
vendor/golang.org/x/crypto/curve25519/square_amd64.s generated vendored Normal file
View File

@ -0,0 +1,132 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This code was translated into a form compatible with 6a from the public
// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
// +build amd64,!gccgo,!appengine
#include "const_amd64.h"
// func square(out, in *[5]uint64)
TEXT ·square(SB),7,$0-16
MOVQ out+0(FP), DI
MOVQ in+8(FP), SI
MOVQ 0(SI),AX
MULQ 0(SI)
MOVQ AX,CX
MOVQ DX,R8
MOVQ 0(SI),AX
SHLQ $1,AX
MULQ 8(SI)
MOVQ AX,R9
MOVQ DX,R10
MOVQ 0(SI),AX
SHLQ $1,AX
MULQ 16(SI)
MOVQ AX,R11
MOVQ DX,R12
MOVQ 0(SI),AX
SHLQ $1,AX
MULQ 24(SI)
MOVQ AX,R13
MOVQ DX,R14
MOVQ 0(SI),AX
SHLQ $1,AX
MULQ 32(SI)
MOVQ AX,R15
MOVQ DX,BX
MOVQ 8(SI),AX
MULQ 8(SI)
ADDQ AX,R11
ADCQ DX,R12
MOVQ 8(SI),AX
SHLQ $1,AX
MULQ 16(SI)
ADDQ AX,R13
ADCQ DX,R14
MOVQ 8(SI),AX
SHLQ $1,AX
MULQ 24(SI)
ADDQ AX,R15
ADCQ DX,BX
MOVQ 8(SI),DX
IMUL3Q $38,DX,AX
MULQ 32(SI)
ADDQ AX,CX
ADCQ DX,R8
MOVQ 16(SI),AX
MULQ 16(SI)
ADDQ AX,R15
ADCQ DX,BX
MOVQ 16(SI),DX
IMUL3Q $38,DX,AX
MULQ 24(SI)
ADDQ AX,CX
ADCQ DX,R8
MOVQ 16(SI),DX
IMUL3Q $38,DX,AX
MULQ 32(SI)
ADDQ AX,R9
ADCQ DX,R10
MOVQ 24(SI),DX
IMUL3Q $19,DX,AX
MULQ 24(SI)
ADDQ AX,R9
ADCQ DX,R10
MOVQ 24(SI),DX
IMUL3Q $38,DX,AX
MULQ 32(SI)
ADDQ AX,R11
ADCQ DX,R12
MOVQ 32(SI),DX
IMUL3Q $19,DX,AX
MULQ 32(SI)
ADDQ AX,R13
ADCQ DX,R14
MOVQ $REDMASK51,SI
SHLQ $13,R8:CX
ANDQ SI,CX
SHLQ $13,R10:R9
ANDQ SI,R9
ADDQ R8,R9
SHLQ $13,R12:R11
ANDQ SI,R11
ADDQ R10,R11
SHLQ $13,R14:R13
ANDQ SI,R13
ADDQ R12,R13
SHLQ $13,BX:R15
ANDQ SI,R15
ADDQ R14,R15
IMUL3Q $19,BX,DX
ADDQ DX,CX
MOVQ CX,DX
SHRQ $51,DX
ADDQ R9,DX
ANDQ SI,CX
MOVQ DX,R8
SHRQ $51,DX
ADDQ R11,DX
ANDQ SI,R8
MOVQ DX,R9
SHRQ $51,DX
ADDQ R13,DX
ANDQ SI,R9
MOVQ DX,AX
SHRQ $51,DX
ADDQ R15,DX
ANDQ SI,AX
MOVQ DX,R10
SHRQ $51,DX
IMUL3Q $19,DX,DX
ADDQ DX,CX
ANDQ SI,R10
MOVQ CX,0(DI)
MOVQ R8,8(DI)
MOVQ R9,16(DI)
MOVQ AX,24(DI)
MOVQ R10,32(DI)
RET

View File

@ -2,11 +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.
// In Go 1.13, the ed25519 package was promoted to the standard library as
// crypto/ed25519, and this package became a wrapper for the standard library one.
//
// +build !go1.13
// Package ed25519 implements the Ed25519 signature algorithm. See // Package ed25519 implements the Ed25519 signature algorithm. See
// https://ed25519.cr.yp.to/. // https://ed25519.cr.yp.to/.
// //

View File

@ -1,73 +0,0 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.13
// Package ed25519 implements the Ed25519 signature algorithm. See
// https://ed25519.cr.yp.to/.
//
// These functions are also compatible with the “Ed25519” function defined in
// RFC 8032. However, unlike RFC 8032's formulation, this package's private key
// representation includes a public key suffix to make multiple signing
// operations with the same key more efficient. This package refers to the RFC
// 8032 private key as the “seed”.
//
// Beginning with Go 1.13, the functionality of this package was moved to the
// standard library as crypto/ed25519. This package only acts as a compatibility
// wrapper.
package ed25519
import (
"crypto/ed25519"
"io"
)
const (
// PublicKeySize is the size, in bytes, of public keys as used in this package.
PublicKeySize = 32
// PrivateKeySize is the size, in bytes, of private keys as used in this package.
PrivateKeySize = 64
// SignatureSize is the size, in bytes, of signatures generated and verified by this package.
SignatureSize = 64
// SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032.
SeedSize = 32
)
// PublicKey is the type of Ed25519 public keys.
//
// This type is an alias for crypto/ed25519's PublicKey type.
// See the crypto/ed25519 package for the methods on this type.
type PublicKey = ed25519.PublicKey
// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer.
//
// This type is an alias for crypto/ed25519's PrivateKey type.
// See the crypto/ed25519 package for the methods on this type.
type PrivateKey = ed25519.PrivateKey
// GenerateKey generates a public/private key pair using entropy from rand.
// If rand is nil, crypto/rand.Reader will be used.
func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
return ed25519.GenerateKey(rand)
}
// NewKeyFromSeed calculates a private key from a seed. It will panic if
// len(seed) is not SeedSize. This function is provided for interoperability
// with RFC 8032. RFC 8032's private keys correspond to seeds in this
// package.
func NewKeyFromSeed(seed []byte) PrivateKey {
return ed25519.NewKeyFromSeed(seed)
}
// Sign signs the message with privateKey and returns a signature. It will
// panic if len(privateKey) is not PrivateKeySize.
func Sign(privateKey PrivateKey, message []byte) []byte {
return ed25519.Sign(privateKey, message)
}
// Verify reports whether sig is a valid signature of message by publicKey. It
// will panic if len(publicKey) is not PublicKeySize.
func Verify(publicKey PublicKey, message, sig []byte) bool {
return ed25519.Verify(publicKey, message, sig)
}

View File

@ -2,7 +2,8 @@
// 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 go1.11,!gccgo,!purego // +build go1.11
// +build !gccgo,!appengine
#include "textflag.h" #include "textflag.h"

View File

@ -0,0 +1,31 @@
// 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 go1.11
// +build !gccgo
package chacha20
const (
haveAsm = true
bufSize = 256
)
//go:noescape
func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32)
func (c *Cipher) xorKeyStreamAsm(dst, src []byte) {
if len(src) >= bufSize {
xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter)
}
if len(src)%bufSize != 0 {
i := len(src) - len(src)%bufSize
c.buf = [bufSize]byte{}
copy(c.buf[:], src[i:])
xorKeyStreamVX(c.buf[:], c.buf[:], &c.key, &c.nonce, &c.counter)
c.len = bufSize - copy(dst[i:], c.buf[:len(src)%bufSize])
}
}

View File

@ -0,0 +1,264 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package ChaCha20 implements the core ChaCha20 function as specified
// in https://tools.ietf.org/html/rfc7539#section-2.3.
package chacha20
import (
"crypto/cipher"
"encoding/binary"
"golang.org/x/crypto/internal/subtle"
)
// assert that *Cipher implements cipher.Stream
var _ cipher.Stream = (*Cipher)(nil)
// Cipher is a stateful instance of ChaCha20 using a particular key
// and nonce. A *Cipher implements the cipher.Stream interface.
type Cipher struct {
key [8]uint32
counter uint32 // incremented after each block
nonce [3]uint32
buf [bufSize]byte // buffer for unused keystream bytes
len int // number of unused keystream bytes at end of buf
}
// New creates a new ChaCha20 stream cipher with the given key and nonce.
// The initial counter value is set to 0.
func New(key [8]uint32, nonce [3]uint32) *Cipher {
return &Cipher{key: key, nonce: nonce}
}
// ChaCha20 constants spelling "expand 32-byte k"
const (
j0 uint32 = 0x61707865
j1 uint32 = 0x3320646e
j2 uint32 = 0x79622d32
j3 uint32 = 0x6b206574
)
func quarterRound(a, b, c, d uint32) (uint32, uint32, uint32, uint32) {
a += b
d ^= a
d = (d << 16) | (d >> 16)
c += d
b ^= c
b = (b << 12) | (b >> 20)
a += b
d ^= a
d = (d << 8) | (d >> 24)
c += d
b ^= c
b = (b << 7) | (b >> 25)
return a, b, c, d
}
// XORKeyStream XORs each byte in the given slice with a byte from the
// cipher's key stream. Dst and src must overlap entirely or not at all.
//
// If len(dst) < len(src), XORKeyStream will panic. It is acceptable
// to pass a dst bigger than src, and in that case, XORKeyStream will
// only update dst[:len(src)] and will not touch the rest of dst.
//
// Multiple calls to XORKeyStream behave as if the concatenation of
// the src buffers was passed in a single run. That is, Cipher
// maintains state and does not reset at each XORKeyStream call.
func (s *Cipher) XORKeyStream(dst, src []byte) {
if len(dst) < len(src) {
panic("chacha20: output smaller than input")
}
if subtle.InexactOverlap(dst[:len(src)], src) {
panic("chacha20: invalid buffer overlap")
}
// xor src with buffered keystream first
if s.len != 0 {
buf := s.buf[len(s.buf)-s.len:]
if len(src) < len(buf) {
buf = buf[:len(src)]
}
td, ts := dst[:len(buf)], src[:len(buf)] // BCE hint
for i, b := range buf {
td[i] = ts[i] ^ b
}
s.len -= len(buf)
if s.len != 0 {
return
}
s.buf = [len(s.buf)]byte{} // zero the empty buffer
src = src[len(buf):]
dst = dst[len(buf):]
}
if len(src) == 0 {
return
}
if haveAsm {
if uint64(len(src))+uint64(s.counter)*64 > (1<<38)-64 {
panic("chacha20: counter overflow")
}
s.xorKeyStreamAsm(dst, src)
return
}
// set up a 64-byte buffer to pad out the final block if needed
// (hoisted out of the main loop to avoid spills)
rem := len(src) % 64 // length of final block
fin := len(src) - rem // index of final block
if rem > 0 {
copy(s.buf[len(s.buf)-64:], src[fin:])
}
// pre-calculate most of the first round
s1, s5, s9, s13 := quarterRound(j1, s.key[1], s.key[5], s.nonce[0])
s2, s6, s10, s14 := quarterRound(j2, s.key[2], s.key[6], s.nonce[1])
s3, s7, s11, s15 := quarterRound(j3, s.key[3], s.key[7], s.nonce[2])
n := len(src)
src, dst = src[:n:n], dst[:n:n] // BCE hint
for i := 0; i < n; i += 64 {
// calculate the remainder of the first round
s0, s4, s8, s12 := quarterRound(j0, s.key[0], s.key[4], s.counter)
// execute the second round
x0, x5, x10, x15 := quarterRound(s0, s5, s10, s15)
x1, x6, x11, x12 := quarterRound(s1, s6, s11, s12)
x2, x7, x8, x13 := quarterRound(s2, s7, s8, s13)
x3, x4, x9, x14 := quarterRound(s3, s4, s9, s14)
// execute the remaining 18 rounds
for i := 0; i < 9; i++ {
x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12)
x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13)
x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14)
x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15)
x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15)
x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12)
x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13)
x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14)
}
x0 += j0
x1 += j1
x2 += j2
x3 += j3
x4 += s.key[0]
x5 += s.key[1]
x6 += s.key[2]
x7 += s.key[3]
x8 += s.key[4]
x9 += s.key[5]
x10 += s.key[6]
x11 += s.key[7]
x12 += s.counter
x13 += s.nonce[0]
x14 += s.nonce[1]
x15 += s.nonce[2]
// increment the counter
s.counter += 1
if s.counter == 0 {
panic("chacha20: counter overflow")
}
// pad to 64 bytes if needed
in, out := src[i:], dst[i:]
if i == fin {
// src[fin:] has already been copied into s.buf before
// the main loop
in, out = s.buf[len(s.buf)-64:], s.buf[len(s.buf)-64:]
}
in, out = in[:64], out[:64] // BCE hint
// XOR the key stream with the source and write out the result
xor(out[0:], in[0:], x0)
xor(out[4:], in[4:], x1)
xor(out[8:], in[8:], x2)
xor(out[12:], in[12:], x3)
xor(out[16:], in[16:], x4)
xor(out[20:], in[20:], x5)
xor(out[24:], in[24:], x6)
xor(out[28:], in[28:], x7)
xor(out[32:], in[32:], x8)
xor(out[36:], in[36:], x9)
xor(out[40:], in[40:], x10)
xor(out[44:], in[44:], x11)
xor(out[48:], in[48:], x12)
xor(out[52:], in[52:], x13)
xor(out[56:], in[56:], x14)
xor(out[60:], in[60:], x15)
}
// copy any trailing bytes out of the buffer and into dst
if rem != 0 {
s.len = 64 - rem
copy(dst[fin:], s.buf[len(s.buf)-64:])
}
}
// Advance discards bytes in the key stream until the next 64 byte block
// boundary is reached and updates the counter accordingly. If the key
// stream is already at a block boundary no bytes will be discarded and
// the counter will be unchanged.
func (s *Cipher) Advance() {
s.len -= s.len % 64
if s.len == 0 {
s.buf = [len(s.buf)]byte{}
}
}
// XORKeyStream crypts bytes from in to out using the given key and counters.
// In and out must overlap entirely or not at all. Counter contains the raw
// ChaCha20 counter bytes (i.e. block counter followed by nonce).
func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) {
s := Cipher{
key: [8]uint32{
binary.LittleEndian.Uint32(key[0:4]),
binary.LittleEndian.Uint32(key[4:8]),
binary.LittleEndian.Uint32(key[8:12]),
binary.LittleEndian.Uint32(key[12:16]),
binary.LittleEndian.Uint32(key[16:20]),
binary.LittleEndian.Uint32(key[20:24]),
binary.LittleEndian.Uint32(key[24:28]),
binary.LittleEndian.Uint32(key[28:32]),
},
nonce: [3]uint32{
binary.LittleEndian.Uint32(counter[4:8]),
binary.LittleEndian.Uint32(counter[8:12]),
binary.LittleEndian.Uint32(counter[12:16]),
},
counter: binary.LittleEndian.Uint32(counter[0:4]),
}
s.XORKeyStream(out, in)
}
// HChaCha20 uses the ChaCha20 core to generate a derived key from a key and a
// nonce. It should only be used as part of the XChaCha20 construction.
func HChaCha20(key *[8]uint32, nonce *[4]uint32) [8]uint32 {
x0, x1, x2, x3 := j0, j1, j2, j3
x4, x5, x6, x7 := key[0], key[1], key[2], key[3]
x8, x9, x10, x11 := key[4], key[5], key[6], key[7]
x12, x13, x14, x15 := nonce[0], nonce[1], nonce[2], nonce[3]
for i := 0; i < 10; i++ {
x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12)
x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13)
x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14)
x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15)
x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15)
x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12)
x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13)
x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14)
}
var out [8]uint32
out[0], out[1], out[2], out[3] = x0, x1, x2, x3
out[4], out[5], out[6], out[7] = x12, x13, x14, x15
return out
}

View File

@ -2,12 +2,15 @@
// 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 !arm64,!s390x,!ppc64le arm64,!go1.11 gccgo purego // +build !arm64,!s390x arm64,!go1.11 gccgo appengine
package chacha20 package chacha20
const bufSize = blockSize const (
bufSize = 64
haveAsm = false
)
func (s *Cipher) xorKeyStreamBlocks(dst, src []byte) { func (*Cipher) xorKeyStreamAsm(dst, src []byte) {
s.xorKeyStreamBlocksGeneric(dst, src) panic("not implemented")
} }

View File

@ -0,0 +1,29 @@
// 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 s390x,!gccgo,!appengine
package chacha20
import (
"golang.org/x/sys/cpu"
)
var haveAsm = cpu.S390X.HasVX
const bufSize = 256
// xorKeyStreamVX is an assembly implementation of XORKeyStream. It must only
// be called when the vector facility is available.
// Implementation in asm_s390x.s.
//go:noescape
func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32, buf *[256]byte, len *int)
func (c *Cipher) xorKeyStreamAsm(dst, src []byte) {
xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter, &c.buf, &c.len)
}
// EXRL targets, DO NOT CALL!
func mvcSrcToBuf()
func mvcBufToDst()

View File

@ -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,!purego // +build s390x,!gccgo,!appengine
#include "go_asm.h" #include "go_asm.h"
#include "textflag.h" #include "textflag.h"
@ -24,6 +24,15 @@ DATA ·constants<>+0x14(SB)/4, $0x3320646e
DATA ·constants<>+0x18(SB)/4, $0x79622d32 DATA ·constants<>+0x18(SB)/4, $0x79622d32
DATA ·constants<>+0x1c(SB)/4, $0x6b206574 DATA ·constants<>+0x1c(SB)/4, $0x6b206574
// EXRL targets:
TEXT ·mvcSrcToBuf(SB), NOFRAME|NOSPLIT, $0
MVC $1, (R1), (R8)
RET
TEXT ·mvcBufToDst(SB), NOFRAME|NOSPLIT, $0
MVC $1, (R8), (R9)
RET
#define BSWAP V5 #define BSWAP V5
#define J0 V6 #define J0 V6
#define KEY0 V7 #define KEY0 V7
@ -135,7 +144,7 @@ DATA ·constants<>+0x1c(SB)/4, $0x6b206574
VMRHF v, w, c \ // c = {a[2], b[2], c[2], d[2]} VMRHF v, w, c \ // c = {a[2], b[2], c[2], d[2]}
VMRLF v, w, d // d = {a[3], b[3], c[3], d[3]} VMRLF v, w, d // d = {a[3], b[3], c[3], d[3]}
// func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32) // func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32, buf *[256]byte, len *int)
TEXT ·xorKeyStreamVX(SB), NOSPLIT, $0 TEXT ·xorKeyStreamVX(SB), NOSPLIT, $0
MOVD $·constants<>(SB), R1 MOVD $·constants<>(SB), R1
MOVD dst+0(FP), R2 // R2=&dst[0] MOVD dst+0(FP), R2 // R2=&dst[0]
@ -143,10 +152,25 @@ TEXT ·xorKeyStreamVX(SB), NOSPLIT, $0
MOVD key+48(FP), R5 // R5=key MOVD key+48(FP), R5 // R5=key
MOVD nonce+56(FP), R6 // R6=nonce MOVD nonce+56(FP), R6 // R6=nonce
MOVD counter+64(FP), R7 // R7=counter MOVD counter+64(FP), R7 // R7=counter
MOVD buf+72(FP), R8 // R8=buf
MOVD len+80(FP), R9 // R9=len
// load BSWAP and J0 // load BSWAP and J0
VLM (R1), BSWAP, J0 VLM (R1), BSWAP, J0
// set up tail buffer
ADD $-1, R4, R12
MOVBZ R12, R12
CMPUBEQ R12, $255, aligned
MOVD R4, R1
AND $~255, R1
MOVD $(R3)(R1*1), R1
EXRL $·mvcSrcToBuf(SB), R12
MOVD $255, R0
SUB R12, R0
MOVD R0, (R9) // update len
aligned:
// setup // setup
MOVD $95, R0 MOVD $95, R0
VLM (R5), KEY0, KEY1 VLM (R5), KEY0, KEY1
@ -193,7 +217,9 @@ loop:
// decrement length // decrement length
ADD $-256, R4 ADD $-256, R4
BLT tail
continue:
// rearrange vectors // rearrange vectors
SHUFFLE(X0, X1, X2, X3, M0, M1, M2, M3) SHUFFLE(X0, X1, X2, X3, M0, M1, M2, M3)
ADDV(J0, X0, X1, X2, X3) ADDV(J0, X0, X1, X2, X3)
@ -219,6 +245,16 @@ loop:
MOVD $256(R3), R3 MOVD $256(R3), R3
CMPBNE R4, $0, chacha CMPBNE R4, $0, chacha
CMPUBEQ R12, $255, return
EXRL $·mvcBufToDst(SB), R12 // len was updated during setup
return:
VSTEF $0, CTR, (R7) VSTEF $0, CTR, (R7)
RET RET
tail:
MOVD R2, R9
MOVD R8, R2
MOVD R8, R3
MOVD $0, R4
JMP continue

View File

@ -4,7 +4,9 @@
package chacha20 package chacha20
import "runtime" import (
"runtime"
)
// Platforms that have fast unaligned 32-bit little endian accesses. // Platforms that have fast unaligned 32-bit little endian accesses.
const unaligned = runtime.GOARCH == "386" || const unaligned = runtime.GOARCH == "386" ||
@ -13,10 +15,10 @@ const unaligned = runtime.GOARCH == "386" ||
runtime.GOARCH == "ppc64le" || runtime.GOARCH == "ppc64le" ||
runtime.GOARCH == "s390x" runtime.GOARCH == "s390x"
// addXor reads a little endian uint32 from src, XORs it with (a + b) and // xor reads a little endian uint32 from src, XORs it with u and
// places the result in little endian byte order in dst. // places the result in little endian byte order in dst.
func addXor(dst, src []byte, a, b uint32) { func xor(dst, src []byte, u uint32) {
_, _ = src[3], dst[3] // bounds check elimination hint _, _ = src[3], dst[3] // eliminate bounds checks
if unaligned { if unaligned {
// The compiler should optimize this code into // The compiler should optimize this code into
// 32-bit unaligned little endian loads and stores. // 32-bit unaligned little endian loads and stores.
@ -27,16 +29,15 @@ func addXor(dst, src []byte, a, b uint32) {
v |= uint32(src[1]) << 8 v |= uint32(src[1]) << 8
v |= uint32(src[2]) << 16 v |= uint32(src[2]) << 16
v |= uint32(src[3]) << 24 v |= uint32(src[3]) << 24
v ^= a + b v ^= u
dst[0] = byte(v) dst[0] = byte(v)
dst[1] = byte(v >> 8) dst[1] = byte(v >> 8)
dst[2] = byte(v >> 16) dst[2] = byte(v >> 16)
dst[3] = byte(v >> 24) dst[3] = byte(v >> 24)
} else { } else {
a += b dst[0] = src[0] ^ byte(u)
dst[0] = src[0] ^ byte(a) dst[1] = src[1] ^ byte(u>>8)
dst[1] = src[1] ^ byte(a>>8) dst[2] = src[2] ^ byte(u>>16)
dst[2] = src[2] ^ byte(a>>16) dst[3] = src[3] ^ byte(u>>24)
dst[3] = src[3] ^ byte(a>>24)
} }
} }

View File

@ -62,11 +62,10 @@ var armorEndOfLine = []byte("-----")
// lineReader wraps a line based reader. It watches for the end of an armor // lineReader wraps a line based reader. It watches for the end of an armor
// block and records the expected CRC value. // block and records the expected CRC value.
type lineReader struct { type lineReader struct {
in *bufio.Reader in *bufio.Reader
buf []byte buf []byte
eof bool eof bool
crc uint32 crc uint32
crcSet bool
} }
func (l *lineReader) Read(p []byte) (n int, err error) { func (l *lineReader) Read(p []byte) (n int, err error) {
@ -88,11 +87,6 @@ func (l *lineReader) Read(p []byte) (n int, err error) {
return 0, ArmorCorrupt return 0, ArmorCorrupt
} }
if bytes.HasPrefix(line, armorEnd) {
l.eof = true
return 0, io.EOF
}
if len(line) == 5 && line[0] == '=' { if len(line) == 5 && line[0] == '=' {
// This is the checksum line // This is the checksum line
var expectedBytes [3]byte var expectedBytes [3]byte
@ -114,7 +108,6 @@ func (l *lineReader) Read(p []byte) (n int, err error) {
} }
l.eof = true l.eof = true
l.crcSet = true
return 0, io.EOF return 0, io.EOF
} }
@ -148,8 +141,10 @@ func (r *openpgpReader) Read(p []byte) (n int, err error) {
n, err = r.b64Reader.Read(p) n, err = r.b64Reader.Read(p)
r.currentCRC = crc24(r.currentCRC, p[:n]) r.currentCRC = crc24(r.currentCRC, p[:n])
if err == io.EOF && r.lReader.crcSet && r.lReader.crc != uint32(r.currentCRC&crc24Mask) { if err == io.EOF {
return 0, ArmorCorrupt if r.lReader.crc != uint32(r.currentCRC&crc24Mask) {
return 0, ArmorCorrupt
}
} }
return return

View File

@ -76,9 +76,7 @@ func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err
// Bleichenbacher, Advances in Cryptology (Crypto '98), // Bleichenbacher, Advances in Cryptology (Crypto '98),
func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) { func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) {
s := new(big.Int).Exp(c1, priv.X, priv.P) s := new(big.Int).Exp(c1, priv.X, priv.P)
if s.ModInverse(s, priv.P) == nil { s.ModInverse(s, priv.P)
return nil, errors.New("elgamal: invalid private key")
}
s.Mul(s, c2) s.Mul(s, c2)
s.Mod(s, priv.P) s.Mod(s, priv.P)
em := s.Bytes() em := s.Bytes()

View File

@ -504,7 +504,7 @@ const defaultRSAKeyBits = 2048
// which may be empty but must not contain any of "()<>\x00". // which may be empty but must not contain any of "()<>\x00".
// If config is nil, sensible defaults will be used. // If config is nil, sensible defaults will be used.
func NewEntity(name, comment, email string, config *packet.Config) (*Entity, error) { func NewEntity(name, comment, email string, config *packet.Config) (*Entity, error) {
creationTime := config.Now() currentTime := config.Now()
bits := defaultRSAKeyBits bits := defaultRSAKeyBits
if config != nil && config.RSABits != 0 { if config != nil && config.RSABits != 0 {
@ -525,8 +525,8 @@ func NewEntity(name, comment, email string, config *packet.Config) (*Entity, err
} }
e := &Entity{ e := &Entity{
PrimaryKey: packet.NewRSAPublicKey(creationTime, &signingPriv.PublicKey), PrimaryKey: packet.NewRSAPublicKey(currentTime, &signingPriv.PublicKey),
PrivateKey: packet.NewRSAPrivateKey(creationTime, signingPriv), PrivateKey: packet.NewRSAPrivateKey(currentTime, signingPriv),
Identities: make(map[string]*Identity), Identities: make(map[string]*Identity),
} }
isPrimaryId := true isPrimaryId := true
@ -534,7 +534,7 @@ func NewEntity(name, comment, email string, config *packet.Config) (*Entity, err
Name: uid.Id, Name: uid.Id,
UserId: uid, UserId: uid,
SelfSignature: &packet.Signature{ SelfSignature: &packet.Signature{
CreationTime: creationTime, CreationTime: currentTime,
SigType: packet.SigTypePositiveCert, SigType: packet.SigTypePositiveCert,
PubKeyAlgo: packet.PubKeyAlgoRSA, PubKeyAlgo: packet.PubKeyAlgoRSA,
Hash: config.Hash(), Hash: config.Hash(),
@ -563,10 +563,10 @@ func NewEntity(name, comment, email string, config *packet.Config) (*Entity, err
e.Subkeys = make([]Subkey, 1) e.Subkeys = make([]Subkey, 1)
e.Subkeys[0] = Subkey{ e.Subkeys[0] = Subkey{
PublicKey: packet.NewRSAPublicKey(creationTime, &encryptingPriv.PublicKey), PublicKey: packet.NewRSAPublicKey(currentTime, &encryptingPriv.PublicKey),
PrivateKey: packet.NewRSAPrivateKey(creationTime, encryptingPriv), PrivateKey: packet.NewRSAPrivateKey(currentTime, encryptingPriv),
Sig: &packet.Signature{ Sig: &packet.Signature{
CreationTime: creationTime, CreationTime: currentTime,
SigType: packet.SigTypeSubkeyBinding, SigType: packet.SigTypeSubkeyBinding,
PubKeyAlgo: packet.PubKeyAlgoRSA, PubKeyAlgo: packet.PubKeyAlgoRSA,
Hash: config.Hash(), Hash: config.Hash(),

View File

@ -5,7 +5,6 @@
package packet package packet
import ( import (
"crypto"
"crypto/rsa" "crypto/rsa"
"encoding/binary" "encoding/binary"
"io" "io"
@ -79,9 +78,8 @@ func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error {
// padding oracle attacks. // padding oracle attacks.
switch priv.PubKeyAlgo { switch priv.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
// Supports both *rsa.PrivateKey and crypto.Decrypter k := priv.PrivateKey.(*rsa.PrivateKey)
k := priv.PrivateKey.(crypto.Decrypter) b, err = rsa.DecryptPKCS1v15(config.Random(), k, padToKeySize(&k.PublicKey, e.encryptedMPI1.bytes))
b, err = k.Decrypt(config.Random(), padToKeySize(k.Public().(*rsa.PublicKey), e.encryptedMPI1.bytes), nil)
case PubKeyAlgoElGamal: case PubKeyAlgoElGamal:
c1 := new(big.Int).SetBytes(e.encryptedMPI1.bytes) c1 := new(big.Int).SetBytes(e.encryptedMPI1.bytes)
c2 := new(big.Int).SetBytes(e.encryptedMPI2.bytes) c2 := new(big.Int).SetBytes(e.encryptedMPI2.bytes)

View File

@ -14,7 +14,6 @@ import (
"crypto/rsa" "crypto/rsa"
"io" "io"
"math/big" "math/big"
"math/bits"
"golang.org/x/crypto/cast5" "golang.org/x/crypto/cast5"
"golang.org/x/crypto/openpgp/errors" "golang.org/x/crypto/openpgp/errors"
@ -101,65 +100,33 @@ func (r *partialLengthReader) Read(p []byte) (n int, err error) {
type partialLengthWriter struct { type partialLengthWriter struct {
w io.WriteCloser w io.WriteCloser
lengthByte [1]byte lengthByte [1]byte
sentFirst bool
buf []byte
} }
// RFC 4880 4.2.2.4: the first partial length MUST be at least 512 octets long.
const minFirstPartialWrite = 512
func (w *partialLengthWriter) Write(p []byte) (n int, err error) { func (w *partialLengthWriter) Write(p []byte) (n int, err error) {
off := 0
if !w.sentFirst {
if len(w.buf) > 0 || len(p) < minFirstPartialWrite {
off = len(w.buf)
w.buf = append(w.buf, p...)
if len(w.buf) < minFirstPartialWrite {
return len(p), nil
}
p = w.buf
w.buf = nil
}
w.sentFirst = true
}
power := uint8(30)
for len(p) > 0 { for len(p) > 0 {
l := 1 << power for power := uint(14); power < 32; power-- {
if len(p) < l { l := 1 << power
power = uint8(bits.Len32(uint32(len(p)))) - 1 if len(p) >= l {
l = 1 << power w.lengthByte[0] = 224 + uint8(power)
} _, err = w.w.Write(w.lengthByte[:])
w.lengthByte[0] = 224 + power if err != nil {
_, err = w.w.Write(w.lengthByte[:]) return
if err == nil { }
var m int var m int
m, err = w.w.Write(p[:l]) m, err = w.w.Write(p[:l])
n += m n += m
} if err != nil {
if err != nil { return
if n < off { }
return 0, err p = p[l:]
break
} }
return n - off, err
} }
p = p[l:]
} }
return n - off, nil return
} }
func (w *partialLengthWriter) Close() error { func (w *partialLengthWriter) Close() error {
if len(w.buf) > 0 {
// In this case we can't send a 512 byte packet.
// Just send what we have.
p := w.buf
w.sentFirst = true
w.buf = nil
if _, err := w.Write(p); err != nil {
return err
}
}
w.lengthByte[0] = 0 w.lengthByte[0] = 0
_, err := w.w.Write(w.lengthByte[:]) _, err := w.w.Write(w.lengthByte[:])
if err != nil { if err != nil {

View File

@ -31,54 +31,54 @@ type PrivateKey struct {
encryptedData []byte encryptedData []byte
cipher CipherFunction cipher CipherFunction
s2k func(out, in []byte) s2k func(out, in []byte)
PrivateKey interface{} // An *{rsa|dsa|ecdsa}.PrivateKey or crypto.Signer/crypto.Decrypter (Decryptor RSA only). PrivateKey interface{} // An *{rsa|dsa|ecdsa}.PrivateKey or a crypto.Signer.
sha1Checksum bool sha1Checksum bool
iv []byte iv []byte
} }
func NewRSAPrivateKey(creationTime time.Time, priv *rsa.PrivateKey) *PrivateKey { func NewRSAPrivateKey(currentTime time.Time, priv *rsa.PrivateKey) *PrivateKey {
pk := new(PrivateKey) pk := new(PrivateKey)
pk.PublicKey = *NewRSAPublicKey(creationTime, &priv.PublicKey) pk.PublicKey = *NewRSAPublicKey(currentTime, &priv.PublicKey)
pk.PrivateKey = priv pk.PrivateKey = priv
return pk return pk
} }
func NewDSAPrivateKey(creationTime time.Time, priv *dsa.PrivateKey) *PrivateKey { func NewDSAPrivateKey(currentTime time.Time, priv *dsa.PrivateKey) *PrivateKey {
pk := new(PrivateKey) pk := new(PrivateKey)
pk.PublicKey = *NewDSAPublicKey(creationTime, &priv.PublicKey) pk.PublicKey = *NewDSAPublicKey(currentTime, &priv.PublicKey)
pk.PrivateKey = priv pk.PrivateKey = priv
return pk return pk
} }
func NewElGamalPrivateKey(creationTime time.Time, priv *elgamal.PrivateKey) *PrivateKey { func NewElGamalPrivateKey(currentTime time.Time, priv *elgamal.PrivateKey) *PrivateKey {
pk := new(PrivateKey) pk := new(PrivateKey)
pk.PublicKey = *NewElGamalPublicKey(creationTime, &priv.PublicKey) pk.PublicKey = *NewElGamalPublicKey(currentTime, &priv.PublicKey)
pk.PrivateKey = priv pk.PrivateKey = priv
return pk return pk
} }
func NewECDSAPrivateKey(creationTime time.Time, priv *ecdsa.PrivateKey) *PrivateKey { func NewECDSAPrivateKey(currentTime time.Time, priv *ecdsa.PrivateKey) *PrivateKey {
pk := new(PrivateKey) pk := new(PrivateKey)
pk.PublicKey = *NewECDSAPublicKey(creationTime, &priv.PublicKey) pk.PublicKey = *NewECDSAPublicKey(currentTime, &priv.PublicKey)
pk.PrivateKey = priv pk.PrivateKey = priv
return pk return pk
} }
// NewSignerPrivateKey creates a PrivateKey from a crypto.Signer that // NewSignerPrivateKey creates a PrivateKey from a crypto.Signer that
// implements RSA or ECDSA. // implements RSA or ECDSA.
func NewSignerPrivateKey(creationTime time.Time, signer crypto.Signer) *PrivateKey { func NewSignerPrivateKey(currentTime time.Time, signer crypto.Signer) *PrivateKey {
pk := new(PrivateKey) pk := new(PrivateKey)
// In general, the public Keys should be used as pointers. We still // In general, the public Keys should be used as pointers. We still
// type-switch on the values, for backwards-compatibility. // type-switch on the values, for backwards-compatibility.
switch pubkey := signer.Public().(type) { switch pubkey := signer.Public().(type) {
case *rsa.PublicKey: case *rsa.PublicKey:
pk.PublicKey = *NewRSAPublicKey(creationTime, pubkey) pk.PublicKey = *NewRSAPublicKey(currentTime, pubkey)
case rsa.PublicKey: case rsa.PublicKey:
pk.PublicKey = *NewRSAPublicKey(creationTime, &pubkey) pk.PublicKey = *NewRSAPublicKey(currentTime, &pubkey)
case *ecdsa.PublicKey: case *ecdsa.PublicKey:
pk.PublicKey = *NewECDSAPublicKey(creationTime, pubkey) pk.PublicKey = *NewECDSAPublicKey(currentTime, pubkey)
case ecdsa.PublicKey: case ecdsa.PublicKey:
pk.PublicKey = *NewECDSAPublicKey(creationTime, &pubkey) pk.PublicKey = *NewECDSAPublicKey(currentTime, &pubkey)
default: default:
panic("openpgp: unknown crypto.Signer type in NewSignerPrivateKey") panic("openpgp: unknown crypto.Signer type in NewSignerPrivateKey")
} }

View File

@ -252,7 +252,6 @@ func Decode(pfxData []byte, password string) (privateKey interface{}, certificat
case bag.Id.Equal(oidPKCS8ShroundedKeyBag): case bag.Id.Equal(oidPKCS8ShroundedKeyBag):
if privateKey != nil { if privateKey != nil {
err = errors.New("pkcs12: expected exactly one key bag") err = errors.New("pkcs12: expected exactly one key bag")
return nil, nil, err
} }
if privateKey, err = decodePkcs8ShroudedKeyBag(bag.Value.Bytes, encodedPassword); err != nil { if privateKey, err = decodePkcs8ShroudedKeyBag(bag.Value.Bytes, encodedPassword); err != nil {

View File

@ -1,39 +0,0 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !go1.13
package poly1305
// Generic fallbacks for the math/bits intrinsics, copied from
// src/math/bits/bits.go. They were added in Go 1.12, but Add64 and Sum64 had
// variable time fallbacks until Go 1.13.
func bitsAdd64(x, y, carry uint64) (sum, carryOut uint64) {
sum = x + y + carry
carryOut = ((x & y) | ((x | y) &^ sum)) >> 63
return
}
func bitsSub64(x, y, borrow uint64) (diff, borrowOut uint64) {
diff = x - y - borrow
borrowOut = ((^x & y) | (^(x ^ y) & diff)) >> 63
return
}
func bitsMul64(x, y uint64) (hi, lo uint64) {
const mask32 = 1<<32 - 1
x0 := x & mask32
x1 := x >> 32
y0 := y & mask32
y1 := y >> 32
w0 := x0 * y0
t := x1*y0 + w0>>32
w1 := t & mask32
w2 := t >> 32
w1 += x0 * y1
hi = x1*y1 + w2 + w1>>32
lo = x * y
return
}

View File

@ -1,21 +0,0 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.13
package poly1305
import "math/bits"
func bitsAdd64(x, y, carry uint64) (sum, carryOut uint64) {
return bits.Add64(x, y, carry)
}
func bitsSub64(x, y, borrow uint64) (diff, borrowOut uint64) {
return bits.Sub64(x, y, borrow)
}
func bitsMul64(x, y uint64) (hi, lo uint64) {
return bits.Mul64(x, y)
}

View File

@ -2,8 +2,10 @@
// 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 !amd64,!ppc64le,!s390x gccgo purego // +build !amd64 gccgo appengine
package poly1305 package poly1305
type mac struct{ macGeneric } type mac struct{ macGeneric }
func newMAC(key *[32]byte) mac { return mac{newMACGeneric(key)} }

View File

@ -22,16 +22,8 @@ import "crypto/subtle"
// TagSize is the size, in bytes, of a poly1305 authenticator. // TagSize is the size, in bytes, of a poly1305 authenticator.
const TagSize = 16 const TagSize = 16
// Sum generates an authenticator for msg using a one-time key and puts the // Verify returns true if mac is a valid authenticator for m with the given
// 16-byte result into out. Authenticating two different messages with the same // key.
// key allows an attacker to forge messages at will.
func Sum(out *[16]byte, m []byte, key *[32]byte) {
h := New(key)
h.Write(m)
h.Sum(out[:0])
}
// Verify returns true if mac is a valid authenticator for m with the given key.
func Verify(mac *[16]byte, m []byte, key *[32]byte) bool { func Verify(mac *[16]byte, m []byte, key *[32]byte) bool {
var tmp [16]byte var tmp [16]byte
Sum(&tmp, m, key) Sum(&tmp, m, key)
@ -48,9 +40,10 @@ func Verify(mac *[16]byte, m []byte, key *[32]byte) bool {
// two different messages with the same key allows an attacker // two different messages with the same key allows an attacker
// to forge messages at will. // to forge messages at will.
func New(key *[32]byte) *MAC { func New(key *[32]byte) *MAC {
m := &MAC{} return &MAC{
initialize(key, &m.macState) mac: newMAC(key),
return m finalized: false,
}
} }
// MAC is an io.Writer computing an authentication tag // MAC is an io.Writer computing an authentication tag
@ -59,7 +52,7 @@ func New(key *[32]byte) *MAC {
// MAC cannot be used like common hash.Hash implementations, // MAC cannot be used like common hash.Hash implementations,
// because using a poly1305 key twice breaks its security. // because using a poly1305 key twice breaks its security.
// Therefore writing data to a running MAC after calling // Therefore writing data to a running MAC after calling
// Sum or Verify causes it to panic. // Sum causes it to panic.
type MAC struct { type MAC struct {
mac // platform-dependent implementation mac // platform-dependent implementation
@ -72,10 +65,10 @@ func (h *MAC) Size() int { return TagSize }
// Write adds more data to the running message authentication code. // Write adds more data to the running message authentication code.
// It never returns an error. // It never returns an error.
// //
// It must not be called after the first call of Sum or Verify. // It must not be called after the first call of Sum.
func (h *MAC) Write(p []byte) (n int, err error) { func (h *MAC) Write(p []byte) (n int, err error) {
if h.finalized { if h.finalized {
panic("poly1305: write to MAC after Sum or Verify") panic("poly1305: write to MAC after Sum")
} }
return h.mac.Write(p) return h.mac.Write(p)
} }
@ -88,12 +81,3 @@ func (h *MAC) Sum(b []byte) []byte {
h.finalized = true h.finalized = true
return append(b, mac[:]...) return append(b, mac[:]...)
} }
// Verify returns whether the authenticator of all data written to
// the message authentication code matches the expected value.
func (h *MAC) Verify(expected []byte) bool {
var mac [TagSize]byte
h.mac.Sum(&mac)
h.finalized = true
return subtle.ConstantTimeCompare(expected, mac[:]) == 1
}

View File

@ -2,46 +2,67 @@
// 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,!purego // +build amd64,!gccgo,!appengine
package poly1305 package poly1305
//go:noescape //go:noescape
func update(state *macState, msg []byte) func initialize(state *[7]uint64, key *[32]byte)
// mac is a wrapper for macGeneric that redirects calls that would have gone to //go:noescape
// updateGeneric to update. func update(state *[7]uint64, msg []byte)
//
// Its Write and Sum methods are otherwise identical to the macGeneric ones, but
// using function pointers would carry a major performance cost.
type mac struct{ macGeneric }
func (h *mac) Write(p []byte) (int, error) { //go:noescape
nn := len(p) func finalize(tag *[TagSize]byte, state *[7]uint64)
// Sum generates an authenticator for m using a one-time key and puts the
// 16-byte result into out. Authenticating two different messages with the same
// key allows an attacker to forge messages at will.
func Sum(out *[16]byte, m []byte, key *[32]byte) {
h := newMAC(key)
h.Write(m)
h.Sum(out)
}
func newMAC(key *[32]byte) (h mac) {
initialize(&h.state, key)
return
}
type mac struct {
state [7]uint64 // := uint64{ h0, h1, h2, r0, r1, pad0, pad1 }
buffer [TagSize]byte
offset int
}
func (h *mac) Write(p []byte) (n int, err error) {
n = len(p)
if h.offset > 0 { if h.offset > 0 {
n := copy(h.buffer[h.offset:], p) remaining := TagSize - h.offset
if h.offset+n < TagSize { if n < remaining {
h.offset += n h.offset += copy(h.buffer[h.offset:], p)
return nn, nil return n, nil
} }
p = p[n:] copy(h.buffer[h.offset:], p[:remaining])
p = p[remaining:]
h.offset = 0 h.offset = 0
update(&h.macState, h.buffer[:]) update(&h.state, h.buffer[:])
} }
if n := len(p) - (len(p) % TagSize); n > 0 { if nn := len(p) - (len(p) % TagSize); nn > 0 {
update(&h.macState, p[:n]) update(&h.state, p[:nn])
p = p[n:] p = p[nn:]
} }
if len(p) > 0 { if len(p) > 0 {
h.offset += copy(h.buffer[h.offset:], p) h.offset += copy(h.buffer[h.offset:], p)
} }
return nn, nil return n, nil
} }
func (h *mac) Sum(out *[16]byte) { func (h *mac) Sum(out *[16]byte) {
state := h.macState state := h.state
if h.offset > 0 { if h.offset > 0 {
update(&state, h.buffer[:h.offset]) update(&state, h.buffer[:h.offset])
} }
finalize(out, &state.h, &state.s) finalize(out, &state)
} }

View File

@ -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,!purego // +build amd64,!gccgo,!appengine
#include "textflag.h" #include "textflag.h"
@ -54,6 +54,10 @@
ADCQ t3, h1; \ ADCQ t3, h1; \
ADCQ $0, h2 ADCQ $0, h2
DATA ·poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF
DATA ·poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC
GLOBL ·poly1305Mask<>(SB), RODATA, $16
// func update(state *[7]uint64, msg []byte) // func update(state *[7]uint64, msg []byte)
TEXT ·update(SB), $0-32 TEXT ·update(SB), $0-32
MOVQ state+0(FP), DI MOVQ state+0(FP), DI
@ -106,3 +110,39 @@ done:
MOVQ R9, 8(DI) MOVQ R9, 8(DI)
MOVQ R10, 16(DI) MOVQ R10, 16(DI)
RET RET
// func initialize(state *[7]uint64, key *[32]byte)
TEXT ·initialize(SB), $0-16
MOVQ state+0(FP), DI
MOVQ key+8(FP), SI
// state[0...7] is initialized with zero
MOVOU 0(SI), X0
MOVOU 16(SI), X1
MOVOU ·poly1305Mask<>(SB), X2
PAND X2, X0
MOVOU X0, 24(DI)
MOVOU X1, 40(DI)
RET
// func finalize(tag *[TagSize]byte, state *[7]uint64)
TEXT ·finalize(SB), $0-16
MOVQ tag+0(FP), DI
MOVQ state+8(FP), SI
MOVQ 0(SI), AX
MOVQ 8(SI), BX
MOVQ 16(SI), CX
MOVQ AX, R8
MOVQ BX, R9
SUBQ $0xFFFFFFFFFFFFFFFB, AX
SBBQ $0xFFFFFFFFFFFFFFFF, BX
SBBQ $3, CX
CMOVQCS R8, AX
CMOVQCS R9, BX
ADDQ 40(SI), AX
ADCQ 48(SI), BX
MOVQ AX, 0(DI)
MOVQ BX, 8(DI)
RET

22
vendor/golang.org/x/crypto/poly1305/sum_arm.go generated vendored Normal file
View File

@ -0,0 +1,22 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build arm,!gccgo,!appengine,!nacl
package poly1305
// This function is implemented in sum_arm.s
//go:noescape
func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]byte)
// Sum generates an authenticator for m using a one-time key and puts the
// 16-byte result into out. Authenticating two different messages with the same
// key allows an attacker to forge messages at will.
func Sum(out *[16]byte, m []byte, key *[32]byte) {
var mPtr *byte
if len(m) > 0 {
mPtr = &m[0]
}
poly1305_auth_armv6(out, mPtr, uint32(len(m)), key)
}

427
vendor/golang.org/x/crypto/poly1305/sum_arm.s generated vendored Normal file
View File

@ -0,0 +1,427 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build arm,!gccgo,!appengine,!nacl
#include "textflag.h"
// This code was translated into a form compatible with 5a from the public
// domain source by Andrew Moon: github.com/floodyberry/poly1305-opt/blob/master/app/extensions/poly1305.
DATA ·poly1305_init_constants_armv6<>+0x00(SB)/4, $0x3ffffff
DATA ·poly1305_init_constants_armv6<>+0x04(SB)/4, $0x3ffff03
DATA ·poly1305_init_constants_armv6<>+0x08(SB)/4, $0x3ffc0ff
DATA ·poly1305_init_constants_armv6<>+0x0c(SB)/4, $0x3f03fff
DATA ·poly1305_init_constants_armv6<>+0x10(SB)/4, $0x00fffff
GLOBL ·poly1305_init_constants_armv6<>(SB), 8, $20
// Warning: the linker may use R11 to synthesize certain instructions. Please
// take care and verify that no synthetic instructions use it.
TEXT poly1305_init_ext_armv6<>(SB), NOSPLIT, $0
// Needs 16 bytes of stack and 64 bytes of space pointed to by R0. (It
// might look like it's only 60 bytes of space but the final four bytes
// will be written by another function.) We need to skip over four
// bytes of stack because that's saving the value of 'g'.
ADD $4, R13, R8
MOVM.IB [R4-R7], (R8)
MOVM.IA.W (R1), [R2-R5]
MOVW $·poly1305_init_constants_armv6<>(SB), R7
MOVW R2, R8
MOVW R2>>26, R9
MOVW R3>>20, g
MOVW R4>>14, R11
MOVW R5>>8, R12
ORR R3<<6, R9, R9
ORR R4<<12, g, g
ORR R5<<18, R11, R11
MOVM.IA (R7), [R2-R6]
AND R8, R2, R2
AND R9, R3, R3
AND g, R4, R4
AND R11, R5, R5
AND R12, R6, R6
MOVM.IA.W [R2-R6], (R0)
EOR R2, R2, R2
EOR R3, R3, R3
EOR R4, R4, R4
EOR R5, R5, R5
EOR R6, R6, R6
MOVM.IA.W [R2-R6], (R0)
MOVM.IA.W (R1), [R2-R5]
MOVM.IA [R2-R6], (R0)
ADD $20, R13, R0
MOVM.DA (R0), [R4-R7]
RET
#define MOVW_UNALIGNED(Rsrc, Rdst, Rtmp, offset) \
MOVBU (offset+0)(Rsrc), Rtmp; \
MOVBU Rtmp, (offset+0)(Rdst); \
MOVBU (offset+1)(Rsrc), Rtmp; \
MOVBU Rtmp, (offset+1)(Rdst); \
MOVBU (offset+2)(Rsrc), Rtmp; \
MOVBU Rtmp, (offset+2)(Rdst); \
MOVBU (offset+3)(Rsrc), Rtmp; \
MOVBU Rtmp, (offset+3)(Rdst)
TEXT poly1305_blocks_armv6<>(SB), NOSPLIT, $0
// Needs 24 bytes of stack for saved registers and then 88 bytes of
// scratch space after that. We assume that 24 bytes at (R13) have
// already been used: four bytes for the link register saved in the
// prelude of poly1305_auth_armv6, four bytes for saving the value of g
// in that function and 16 bytes of scratch space used around
// poly1305_finish_ext_armv6_skip1.
ADD $24, R13, R12
MOVM.IB [R4-R8, R14], (R12)
MOVW R0, 88(R13)
MOVW R1, 92(R13)
MOVW R2, 96(R13)
MOVW R1, R14
MOVW R2, R12
MOVW 56(R0), R8
WORD $0xe1180008 // TST R8, R8 not working see issue 5921
EOR R6, R6, R6
MOVW.EQ $(1<<24), R6
MOVW R6, 84(R13)
ADD $116, R13, g
MOVM.IA (R0), [R0-R9]
MOVM.IA [R0-R4], (g)
CMP $16, R12
BLO poly1305_blocks_armv6_done
poly1305_blocks_armv6_mainloop:
WORD $0xe31e0003 // TST R14, #3 not working see issue 5921
BEQ poly1305_blocks_armv6_mainloop_aligned
ADD $100, R13, g
MOVW_UNALIGNED(R14, g, R0, 0)
MOVW_UNALIGNED(R14, g, R0, 4)
MOVW_UNALIGNED(R14, g, R0, 8)
MOVW_UNALIGNED(R14, g, R0, 12)
MOVM.IA (g), [R0-R3]
ADD $16, R14
B poly1305_blocks_armv6_mainloop_loaded
poly1305_blocks_armv6_mainloop_aligned:
MOVM.IA.W (R14), [R0-R3]
poly1305_blocks_armv6_mainloop_loaded:
MOVW R0>>26, g
MOVW R1>>20, R11
MOVW R2>>14, R12
MOVW R14, 92(R13)
MOVW R3>>8, R4
ORR R1<<6, g, g
ORR R2<<12, R11, R11
ORR R3<<18, R12, R12
BIC $0xfc000000, R0, R0
BIC $0xfc000000, g, g
MOVW 84(R13), R3
BIC $0xfc000000, R11, R11
BIC $0xfc000000, R12, R12
ADD R0, R5, R5
ADD g, R6, R6
ORR R3, R4, R4
ADD R11, R7, R7
ADD $116, R13, R14
ADD R12, R8, R8
ADD R4, R9, R9
MOVM.IA (R14), [R0-R4]
MULLU R4, R5, (R11, g)
MULLU R3, R5, (R14, R12)
MULALU R3, R6, (R11, g)
MULALU R2, R6, (R14, R12)
MULALU R2, R7, (R11, g)
MULALU R1, R7, (R14, R12)
ADD R4<<2, R4, R4
ADD R3<<2, R3, R3
MULALU R1, R8, (R11, g)
MULALU R0, R8, (R14, R12)
MULALU R0, R9, (R11, g)
MULALU R4, R9, (R14, R12)
MOVW g, 76(R13)
MOVW R11, 80(R13)
MOVW R12, 68(R13)
MOVW R14, 72(R13)
MULLU R2, R5, (R11, g)
MULLU R1, R5, (R14, R12)
MULALU R1, R6, (R11, g)
MULALU R0, R6, (R14, R12)
MULALU R0, R7, (R11, g)
MULALU R4, R7, (R14, R12)
ADD R2<<2, R2, R2
ADD R1<<2, R1, R1
MULALU R4, R8, (R11, g)
MULALU R3, R8, (R14, R12)
MULALU R3, R9, (R11, g)
MULALU R2, R9, (R14, R12)
MOVW g, 60(R13)
MOVW R11, 64(R13)
MOVW R12, 52(R13)
MOVW R14, 56(R13)
MULLU R0, R5, (R11, g)
MULALU R4, R6, (R11, g)
MULALU R3, R7, (R11, g)
MULALU R2, R8, (R11, g)
MULALU R1, R9, (R11, g)
ADD $52, R13, R0
MOVM.IA (R0), [R0-R7]
MOVW g>>26, R12
MOVW R4>>26, R14
ORR R11<<6, R12, R12
ORR R5<<6, R14, R14
BIC $0xfc000000, g, g
BIC $0xfc000000, R4, R4
ADD.S R12, R0, R0
ADC $0, R1, R1
ADD.S R14, R6, R6
ADC $0, R7, R7
MOVW R0>>26, R12
MOVW R6>>26, R14
ORR R1<<6, R12, R12
ORR R7<<6, R14, R14
BIC $0xfc000000, R0, R0
BIC $0xfc000000, R6, R6
ADD R14<<2, R14, R14
ADD.S R12, R2, R2
ADC $0, R3, R3
ADD R14, g, g
MOVW R2>>26, R12
MOVW g>>26, R14
ORR R3<<6, R12, R12
BIC $0xfc000000, g, R5
BIC $0xfc000000, R2, R7
ADD R12, R4, R4
ADD R14, R0, R0
MOVW R4>>26, R12
BIC $0xfc000000, R4, R8
ADD R12, R6, R9
MOVW 96(R13), R12
MOVW 92(R13), R14
MOVW R0, R6
CMP $32, R12
SUB $16, R12, R12
MOVW R12, 96(R13)
BHS poly1305_blocks_armv6_mainloop
poly1305_blocks_armv6_done:
MOVW 88(R13), R12
MOVW R5, 20(R12)
MOVW R6, 24(R12)
MOVW R7, 28(R12)
MOVW R8, 32(R12)
MOVW R9, 36(R12)
ADD $48, R13, R0
MOVM.DA (R0), [R4-R8, R14]
RET
#define MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp) \
MOVBU.P 1(Rsrc), Rtmp; \
MOVBU.P Rtmp, 1(Rdst); \
MOVBU.P 1(Rsrc), Rtmp; \
MOVBU.P Rtmp, 1(Rdst)
#define MOVWP_UNALIGNED(Rsrc, Rdst, Rtmp) \
MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp); \
MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp)
// func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]key)
TEXT ·poly1305_auth_armv6(SB), $196-16
// The value 196, just above, is the sum of 64 (the size of the context
// structure) and 132 (the amount of stack needed).
//
// At this point, the stack pointer (R13) has been moved down. It
// points to the saved link register and there's 196 bytes of free
// space above it.
//
// The stack for this function looks like:
//
// +---------------------
// |
// | 64 bytes of context structure
// |
// +---------------------
// |
// | 112 bytes for poly1305_blocks_armv6
// |
// +---------------------
// | 16 bytes of final block, constructed at
// | poly1305_finish_ext_armv6_skip8
// +---------------------
// | four bytes of saved 'g'
// +---------------------
// | lr, saved by prelude <- R13 points here
// +---------------------
MOVW g, 4(R13)
MOVW out+0(FP), R4
MOVW m+4(FP), R5
MOVW mlen+8(FP), R6
MOVW key+12(FP), R7
ADD $136, R13, R0 // 136 = 4 + 4 + 16 + 112
MOVW R7, R1
// poly1305_init_ext_armv6 will write to the stack from R13+4, but
// that's ok because none of the other values have been written yet.
BL poly1305_init_ext_armv6<>(SB)
BIC.S $15, R6, R2
BEQ poly1305_auth_armv6_noblocks
ADD $136, R13, R0
MOVW R5, R1
ADD R2, R5, R5
SUB R2, R6, R6
BL poly1305_blocks_armv6<>(SB)
poly1305_auth_armv6_noblocks:
ADD $136, R13, R0
MOVW R5, R1
MOVW R6, R2
MOVW R4, R3
MOVW R0, R5
MOVW R1, R6
MOVW R2, R7
MOVW R3, R8
AND.S R2, R2, R2
BEQ poly1305_finish_ext_armv6_noremaining
EOR R0, R0
ADD $8, R13, R9 // 8 = offset to 16 byte scratch space
MOVW R0, (R9)
MOVW R0, 4(R9)
MOVW R0, 8(R9)
MOVW R0, 12(R9)
WORD $0xe3110003 // TST R1, #3 not working see issue 5921
BEQ poly1305_finish_ext_armv6_aligned
WORD $0xe3120008 // TST R2, #8 not working see issue 5921
BEQ poly1305_finish_ext_armv6_skip8
MOVWP_UNALIGNED(R1, R9, g)
MOVWP_UNALIGNED(R1, R9, g)
poly1305_finish_ext_armv6_skip8:
WORD $0xe3120004 // TST $4, R2 not working see issue 5921
BEQ poly1305_finish_ext_armv6_skip4
MOVWP_UNALIGNED(R1, R9, g)
poly1305_finish_ext_armv6_skip4:
WORD $0xe3120002 // TST $2, R2 not working see issue 5921
BEQ poly1305_finish_ext_armv6_skip2
MOVHUP_UNALIGNED(R1, R9, g)
B poly1305_finish_ext_armv6_skip2
poly1305_finish_ext_armv6_aligned:
WORD $0xe3120008 // TST R2, #8 not working see issue 5921
BEQ poly1305_finish_ext_armv6_skip8_aligned
MOVM.IA.W (R1), [g-R11]
MOVM.IA.W [g-R11], (R9)
poly1305_finish_ext_armv6_skip8_aligned:
WORD $0xe3120004 // TST $4, R2 not working see issue 5921
BEQ poly1305_finish_ext_armv6_skip4_aligned
MOVW.P 4(R1), g
MOVW.P g, 4(R9)
poly1305_finish_ext_armv6_skip4_aligned:
WORD $0xe3120002 // TST $2, R2 not working see issue 5921
BEQ poly1305_finish_ext_armv6_skip2
MOVHU.P 2(R1), g
MOVH.P g, 2(R9)
poly1305_finish_ext_armv6_skip2:
WORD $0xe3120001 // TST $1, R2 not working see issue 5921
BEQ poly1305_finish_ext_armv6_skip1
MOVBU.P 1(R1), g
MOVBU.P g, 1(R9)
poly1305_finish_ext_armv6_skip1:
MOVW $1, R11
MOVBU R11, 0(R9)
MOVW R11, 56(R5)
MOVW R5, R0
ADD $8, R13, R1
MOVW $16, R2
BL poly1305_blocks_armv6<>(SB)
poly1305_finish_ext_armv6_noremaining:
MOVW 20(R5), R0
MOVW 24(R5), R1
MOVW 28(R5), R2
MOVW 32(R5), R3
MOVW 36(R5), R4
MOVW R4>>26, R12
BIC $0xfc000000, R4, R4
ADD R12<<2, R12, R12
ADD R12, R0, R0
MOVW R0>>26, R12
BIC $0xfc000000, R0, R0
ADD R12, R1, R1
MOVW R1>>26, R12
BIC $0xfc000000, R1, R1
ADD R12, R2, R2
MOVW R2>>26, R12
BIC $0xfc000000, R2, R2
ADD R12, R3, R3
MOVW R3>>26, R12
BIC $0xfc000000, R3, R3
ADD R12, R4, R4
ADD $5, R0, R6
MOVW R6>>26, R12
BIC $0xfc000000, R6, R6
ADD R12, R1, R7
MOVW R7>>26, R12
BIC $0xfc000000, R7, R7
ADD R12, R2, g
MOVW g>>26, R12
BIC $0xfc000000, g, g
ADD R12, R3, R11
MOVW $-(1<<26), R12
ADD R11>>26, R12, R12
BIC $0xfc000000, R11, R11
ADD R12, R4, R9
MOVW R9>>31, R12
SUB $1, R12
AND R12, R6, R6
AND R12, R7, R7
AND R12, g, g
AND R12, R11, R11
AND R12, R9, R9
MVN R12, R12
AND R12, R0, R0
AND R12, R1, R1
AND R12, R2, R2
AND R12, R3, R3
AND R12, R4, R4
ORR R6, R0, R0
ORR R7, R1, R1
ORR g, R2, R2
ORR R11, R3, R3
ORR R9, R4, R4
ORR R1<<26, R0, R0
MOVW R1>>6, R1
ORR R2<<20, R1, R1
MOVW R2>>12, R2
ORR R3<<14, R2, R2
MOVW R3>>18, R3
ORR R4<<8, R3, R3
MOVW 40(R5), R6
MOVW 44(R5), R7
MOVW 48(R5), g
MOVW 52(R5), R11
ADD.S R6, R0, R0
ADC.S R7, R1, R1
ADC.S g, R2, R2
ADC.S R11, R3, R3
MOVM.IA [R0-R3], (R8)
MOVW R5, R12
EOR R0, R0, R0
EOR R1, R1, R1
EOR R2, R2, R2
EOR R3, R3, R3
EOR R4, R4, R4
EOR R5, R5, R5
EOR R6, R6, R6
EOR R7, R7, R7
MOVM.IA.W [R0-R7], (R12)
MOVM.IA [R0-R7], (R12)
MOVW 4(R13), g
RET

View File

@ -2,309 +2,171 @@
// 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.
// This file provides the generic implementation of Sum and MAC. Other files
// might provide optimized assembly implementations of some of this code.
package poly1305 package poly1305
import "encoding/binary" import "encoding/binary"
// Poly1305 [RFC 7539] is a relatively simple algorithm: the authentication tag const (
// for a 64 bytes message is approximately msgBlock = uint32(1 << 24)
// finalBlock = uint32(0)
// s + m[0:16] * r⁴ + m[16:32] * r³ + m[32:48] * r² + m[48:64] * r mod 2¹³⁰ - 5 )
//
// for some secret r and s. It can be computed sequentially like
//
// for len(msg) > 0:
// h += read(msg, 16)
// h *= r
// h %= 2¹³⁰ - 5
// return h + s
//
// All the complexity is about doing performant constant-time math on numbers
// larger than any available numeric type.
// sumGeneric generates an authenticator for msg using a one-time key and
// puts the 16-byte result into out. This is the generic implementation of
// Sum and should be called if no assembly implementation is available.
func sumGeneric(out *[TagSize]byte, msg []byte, key *[32]byte) { func sumGeneric(out *[TagSize]byte, msg []byte, key *[32]byte) {
h := newMACGeneric(key) h := newMACGeneric(key)
h.Write(msg) h.Write(msg)
h.Sum(out) h.Sum(out)
} }
func newMACGeneric(key *[32]byte) macGeneric { func newMACGeneric(key *[32]byte) (h macGeneric) {
m := macGeneric{} h.r[0] = binary.LittleEndian.Uint32(key[0:]) & 0x3ffffff
initialize(key, &m.macState) h.r[1] = (binary.LittleEndian.Uint32(key[3:]) >> 2) & 0x3ffff03
return m h.r[2] = (binary.LittleEndian.Uint32(key[6:]) >> 4) & 0x3ffc0ff
} h.r[3] = (binary.LittleEndian.Uint32(key[9:]) >> 6) & 0x3f03fff
h.r[4] = (binary.LittleEndian.Uint32(key[12:]) >> 8) & 0x00fffff
// macState holds numbers in saturated 64-bit little-endian limbs. That is, h.s[0] = binary.LittleEndian.Uint32(key[16:])
// the value of [x0, x1, x2] is x[0] + x[1] * 2⁶⁴ + x[2] * 2¹²⁸. h.s[1] = binary.LittleEndian.Uint32(key[20:])
type macState struct { h.s[2] = binary.LittleEndian.Uint32(key[24:])
// h is the main accumulator. It is to be interpreted modulo 2¹³⁰ - 5, but h.s[3] = binary.LittleEndian.Uint32(key[28:])
// can grow larger during and after rounds. It must, however, remain below return
// 2 * (2¹³⁰ - 5).
h [3]uint64
// r and s are the private key components.
r [2]uint64
s [2]uint64
} }
type macGeneric struct { type macGeneric struct {
macState h, r [5]uint32
s [4]uint32
buffer [TagSize]byte buffer [TagSize]byte
offset int offset int
} }
// Write splits the incoming message into TagSize chunks, and passes them to func (h *macGeneric) Write(p []byte) (n int, err error) {
// update. It buffers incomplete chunks. n = len(p)
func (h *macGeneric) Write(p []byte) (int, error) {
nn := len(p)
if h.offset > 0 { if h.offset > 0 {
n := copy(h.buffer[h.offset:], p) remaining := TagSize - h.offset
if h.offset+n < TagSize { if n < remaining {
h.offset += n h.offset += copy(h.buffer[h.offset:], p)
return nn, nil return n, nil
} }
p = p[n:] copy(h.buffer[h.offset:], p[:remaining])
p = p[remaining:]
h.offset = 0 h.offset = 0
updateGeneric(&h.macState, h.buffer[:]) updateGeneric(h.buffer[:], msgBlock, &(h.h), &(h.r))
} }
if n := len(p) - (len(p) % TagSize); n > 0 { if nn := len(p) - (len(p) % TagSize); nn > 0 {
updateGeneric(&h.macState, p[:n]) updateGeneric(p, msgBlock, &(h.h), &(h.r))
p = p[n:] p = p[nn:]
} }
if len(p) > 0 { if len(p) > 0 {
h.offset += copy(h.buffer[h.offset:], p) h.offset += copy(h.buffer[h.offset:], p)
} }
return nn, nil return n, nil
} }
// Sum flushes the last incomplete chunk from the buffer, if any, and generates func (h *macGeneric) Sum(out *[16]byte) {
// the MAC output. It does not modify its state, in order to allow for multiple H, R := h.h, h.r
// calls to Sum, even if no Write is allowed after Sum.
func (h *macGeneric) Sum(out *[TagSize]byte) {
state := h.macState
if h.offset > 0 { if h.offset > 0 {
updateGeneric(&state, h.buffer[:h.offset]) var buffer [TagSize]byte
copy(buffer[:], h.buffer[:h.offset])
buffer[h.offset] = 1 // invariant: h.offset < TagSize
updateGeneric(buffer[:], finalBlock, &H, &R)
} }
finalize(out, &state.h, &state.s) finalizeGeneric(out, &H, &(h.s))
} }
// [rMask0, rMask1] is the specified Poly1305 clamping mask in little-endian. It func updateGeneric(msg []byte, flag uint32, h, r *[5]uint32) {
// clears some bits of the secret coefficient to make it possible to implement h0, h1, h2, h3, h4 := h[0], h[1], h[2], h[3], h[4]
// multiplication more efficiently. r0, r1, r2, r3, r4 := uint64(r[0]), uint64(r[1]), uint64(r[2]), uint64(r[3]), uint64(r[4])
const ( R1, R2, R3, R4 := r1*5, r2*5, r3*5, r4*5
rMask0 = 0x0FFFFFFC0FFFFFFF
rMask1 = 0x0FFFFFFC0FFFFFFC
)
// initialize loads the 256-bit key into the two 128-bit secret values r and s. for len(msg) >= TagSize {
func initialize(key *[32]byte, m *macState) { // h += msg
m.r[0] = binary.LittleEndian.Uint64(key[0:8]) & rMask0 h0 += binary.LittleEndian.Uint32(msg[0:]) & 0x3ffffff
m.r[1] = binary.LittleEndian.Uint64(key[8:16]) & rMask1 h1 += (binary.LittleEndian.Uint32(msg[3:]) >> 2) & 0x3ffffff
m.s[0] = binary.LittleEndian.Uint64(key[16:24]) h2 += (binary.LittleEndian.Uint32(msg[6:]) >> 4) & 0x3ffffff
m.s[1] = binary.LittleEndian.Uint64(key[24:32]) h3 += (binary.LittleEndian.Uint32(msg[9:]) >> 6) & 0x3ffffff
} h4 += (binary.LittleEndian.Uint32(msg[12:]) >> 8) | flag
// uint128 holds a 128-bit number as two 64-bit limbs, for use with the // h *= r
// bits.Mul64 and bits.Add64 intrinsics. d0 := (uint64(h0) * r0) + (uint64(h1) * R4) + (uint64(h2) * R3) + (uint64(h3) * R2) + (uint64(h4) * R1)
type uint128 struct { d1 := (d0 >> 26) + (uint64(h0) * r1) + (uint64(h1) * r0) + (uint64(h2) * R4) + (uint64(h3) * R3) + (uint64(h4) * R2)
lo, hi uint64 d2 := (d1 >> 26) + (uint64(h0) * r2) + (uint64(h1) * r1) + (uint64(h2) * r0) + (uint64(h3) * R4) + (uint64(h4) * R3)
} d3 := (d2 >> 26) + (uint64(h0) * r3) + (uint64(h1) * r2) + (uint64(h2) * r1) + (uint64(h3) * r0) + (uint64(h4) * R4)
d4 := (d3 >> 26) + (uint64(h0) * r4) + (uint64(h1) * r3) + (uint64(h2) * r2) + (uint64(h3) * r1) + (uint64(h4) * r0)
func mul64(a, b uint64) uint128 { // h %= p
hi, lo := bitsMul64(a, b) h0 = uint32(d0) & 0x3ffffff
return uint128{lo, hi} h1 = uint32(d1) & 0x3ffffff
} h2 = uint32(d2) & 0x3ffffff
h3 = uint32(d3) & 0x3ffffff
h4 = uint32(d4) & 0x3ffffff
func add128(a, b uint128) uint128 { h0 += uint32(d4>>26) * 5
lo, c := bitsAdd64(a.lo, b.lo, 0) h1 += h0 >> 26
hi, c := bitsAdd64(a.hi, b.hi, c) h0 = h0 & 0x3ffffff
if c != 0 {
panic("poly1305: unexpected overflow")
}
return uint128{lo, hi}
}
func shiftRightBy2(a uint128) uint128 { msg = msg[TagSize:]
a.lo = a.lo>>2 | (a.hi&3)<<62
a.hi = a.hi >> 2
return a
}
// updateGeneric absorbs msg into the state.h accumulator. For each chunk m of
// 128 bits of message, it computes
//
// h₊ = (h + m) * r mod 2¹³⁰ - 5
//
// If the msg length is not a multiple of TagSize, it assumes the last
// incomplete chunk is the final one.
func updateGeneric(state *macState, msg []byte) {
h0, h1, h2 := state.h[0], state.h[1], state.h[2]
r0, r1 := state.r[0], state.r[1]
for len(msg) > 0 {
var c uint64
// For the first step, h + m, we use a chain of bits.Add64 intrinsics.
// The resulting value of h might exceed 2¹³⁰ - 5, but will be partially
// reduced at the end of the multiplication below.
//
// The spec requires us to set a bit just above the message size, not to
// hide leading zeroes. For full chunks, that's 1 << 128, so we can just
// add 1 to the most significant (2¹²⁸) limb, h2.
if len(msg) >= TagSize {
h0, c = bitsAdd64(h0, binary.LittleEndian.Uint64(msg[0:8]), 0)
h1, c = bitsAdd64(h1, binary.LittleEndian.Uint64(msg[8:16]), c)
h2 += c + 1
msg = msg[TagSize:]
} else {
var buf [TagSize]byte
copy(buf[:], msg)
buf[len(msg)] = 1
h0, c = bitsAdd64(h0, binary.LittleEndian.Uint64(buf[0:8]), 0)
h1, c = bitsAdd64(h1, binary.LittleEndian.Uint64(buf[8:16]), c)
h2 += c
msg = nil
}
// Multiplication of big number limbs is similar to elementary school
// columnar multiplication. Instead of digits, there are 64-bit limbs.
//
// We are multiplying a 3 limbs number, h, by a 2 limbs number, r.
//
// h2 h1 h0 x
// r1 r0 =
// ----------------
// h2r0 h1r0 h0r0 <-- individual 128-bit products
// + h2r1 h1r1 h0r1
// ------------------------
// m3 m2 m1 m0 <-- result in 128-bit overlapping limbs
// ------------------------
// m3.hi m2.hi m1.hi m0.hi <-- carry propagation
// + m3.lo m2.lo m1.lo m0.lo
// -------------------------------
// t4 t3 t2 t1 t0 <-- final result in 64-bit limbs
//
// The main difference from pen-and-paper multiplication is that we do
// carry propagation in a separate step, as if we wrote two digit sums
// at first (the 128-bit limbs), and then carried the tens all at once.
h0r0 := mul64(h0, r0)
h1r0 := mul64(h1, r0)
h2r0 := mul64(h2, r0)
h0r1 := mul64(h0, r1)
h1r1 := mul64(h1, r1)
h2r1 := mul64(h2, r1)
// Since h2 is known to be at most 7 (5 + 1 + 1), and r0 and r1 have their
// top 4 bits cleared by rMask{0,1}, we know that their product is not going
// to overflow 64 bits, so we can ignore the high part of the products.
//
// This also means that the product doesn't have a fifth limb (t4).
if h2r0.hi != 0 {
panic("poly1305: unexpected overflow")
}
if h2r1.hi != 0 {
panic("poly1305: unexpected overflow")
}
m0 := h0r0
m1 := add128(h1r0, h0r1) // These two additions don't overflow thanks again
m2 := add128(h2r0, h1r1) // to the 4 masked bits at the top of r0 and r1.
m3 := h2r1
t0 := m0.lo
t1, c := bitsAdd64(m1.lo, m0.hi, 0)
t2, c := bitsAdd64(m2.lo, m1.hi, c)
t3, _ := bitsAdd64(m3.lo, m2.hi, c)
// Now we have the result as 4 64-bit limbs, and we need to reduce it
// modulo 2¹³⁰ - 5. The special shape of this Crandall prime lets us do
// a cheap partial reduction according to the reduction identity
//
// c * 2¹³⁰ + n = c * 5 + n mod 2¹³⁰ - 5
//
// because 2¹³⁰ = 5 mod 2¹³⁰ - 5. Partial reduction since the result is
// likely to be larger than 2¹³⁰ - 5, but still small enough to fit the
// assumptions we make about h in the rest of the code.
//
// See also https://speakerdeck.com/gtank/engineering-prime-numbers?slide=23
// We split the final result at the 2¹³⁰ mark into h and cc, the carry.
// Note that the carry bits are effectively shifted left by 2, in other
// words, cc = c * 4 for the c in the reduction identity.
h0, h1, h2 = t0, t1, t2&maskLow2Bits
cc := uint128{t2 & maskNotLow2Bits, t3}
// To add c * 5 to h, we first add cc = c * 4, and then add (cc >> 2) = c.
h0, c = bitsAdd64(h0, cc.lo, 0)
h1, c = bitsAdd64(h1, cc.hi, c)
h2 += c
cc = shiftRightBy2(cc)
h0, c = bitsAdd64(h0, cc.lo, 0)
h1, c = bitsAdd64(h1, cc.hi, c)
h2 += c
// h2 is at most 3 + 1 + 1 = 5, making the whole of h at most
//
// 5 * 2¹²⁸ + (2¹²⁸ - 1) = 6 * 2¹²⁸ - 1
} }
state.h[0], state.h[1], state.h[2] = h0, h1, h2 h[0], h[1], h[2], h[3], h[4] = h0, h1, h2, h3, h4
} }
const ( func finalizeGeneric(out *[TagSize]byte, h *[5]uint32, s *[4]uint32) {
maskLow2Bits uint64 = 0x0000000000000003 h0, h1, h2, h3, h4 := h[0], h[1], h[2], h[3], h[4]
maskNotLow2Bits uint64 = ^maskLow2Bits
)
// select64 returns x if v == 1 and y if v == 0, in constant time. // h %= p reduction
func select64(v, x, y uint64) uint64 { return ^(v-1)&x | (v-1)&y } h2 += h1 >> 26
h1 &= 0x3ffffff
h3 += h2 >> 26
h2 &= 0x3ffffff
h4 += h3 >> 26
h3 &= 0x3ffffff
h0 += 5 * (h4 >> 26)
h4 &= 0x3ffffff
h1 += h0 >> 26
h0 &= 0x3ffffff
// [p0, p1, p2] is 2¹³⁰ - 5 in little endian order. // h - p
const ( t0 := h0 + 5
p0 = 0xFFFFFFFFFFFFFFFB t1 := h1 + (t0 >> 26)
p1 = 0xFFFFFFFFFFFFFFFF t2 := h2 + (t1 >> 26)
p2 = 0x0000000000000003 t3 := h3 + (t2 >> 26)
) t4 := h4 + (t3 >> 26) - (1 << 26)
t0 &= 0x3ffffff
t1 &= 0x3ffffff
t2 &= 0x3ffffff
t3 &= 0x3ffffff
// finalize completes the modular reduction of h and computes // select h if h < p else h - p
// t_mask := (t4 >> 31) - 1
// out = h + s mod 2¹²⁸ h_mask := ^t_mask
// h0 = (h0 & h_mask) | (t0 & t_mask)
func finalize(out *[TagSize]byte, h *[3]uint64, s *[2]uint64) { h1 = (h1 & h_mask) | (t1 & t_mask)
h0, h1, h2 := h[0], h[1], h[2] h2 = (h2 & h_mask) | (t2 & t_mask)
h3 = (h3 & h_mask) | (t3 & t_mask)
h4 = (h4 & h_mask) | (t4 & t_mask)
// After the partial reduction in updateGeneric, h might be more than // h %= 2^128
// 2¹³⁰ - 5, but will be less than 2 * (2¹³⁰ - 5). To complete the reduction h0 |= h1 << 26
// in constant time, we compute t = h - (2¹³⁰ - 5), and select h as the h1 = ((h1 >> 6) | (h2 << 20))
// result if the subtraction underflows, and t otherwise. h2 = ((h2 >> 12) | (h3 << 14))
h3 = ((h3 >> 18) | (h4 << 8))
hMinusP0, b := bitsSub64(h0, p0, 0) // s: the s part of the key
hMinusP1, b := bitsSub64(h1, p1, b) // tag = (h + s) % (2^128)
_, b = bitsSub64(h2, p2, b) t := uint64(h0) + uint64(s[0])
h0 = uint32(t)
t = uint64(h1) + uint64(s[1]) + (t >> 32)
h1 = uint32(t)
t = uint64(h2) + uint64(s[2]) + (t >> 32)
h2 = uint32(t)
t = uint64(h3) + uint64(s[3]) + (t >> 32)
h3 = uint32(t)
// h = h if h < p else h - p binary.LittleEndian.PutUint32(out[0:], h0)
h0 = select64(b, h0, hMinusP0) binary.LittleEndian.PutUint32(out[4:], h1)
h1 = select64(b, h1, hMinusP1) binary.LittleEndian.PutUint32(out[8:], h2)
binary.LittleEndian.PutUint32(out[12:], h3)
// Finally, we compute the last Poly1305 step
//
// tag = h + s mod 2¹²⁸
//
// by just doing a wide addition with the 128 low bits of h and discarding
// the overflow.
h0, c := bitsAdd64(h0, s[0], 0)
h1, _ = bitsAdd64(h1, s[1], c)
binary.LittleEndian.PutUint64(out[0:8], h0)
binary.LittleEndian.PutUint64(out[8:16], h1)
} }

16
vendor/golang.org/x/crypto/poly1305/sum_noasm.go generated vendored Normal file
View File

@ -0,0 +1,16 @@
// 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 s390x,!go1.11 !arm,!amd64,!s390x gccgo appengine nacl
package poly1305
// Sum generates an authenticator for msg using a one-time key and puts the
// 16-byte result into out. Authenticating two different messages with the same
// key allows an attacker to forge messages at will.
func Sum(out *[TagSize]byte, msg []byte, key *[32]byte) {
h := newMAC(key)
h.Write(msg)
h.Sum(out)
}

View File

@ -1,47 +0,0 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !gccgo,!purego
package poly1305
//go:noescape
func update(state *macState, msg []byte)
// mac is a wrapper for macGeneric that redirects calls that would have gone to
// updateGeneric to update.
//
// Its Write and Sum methods are otherwise identical to the macGeneric ones, but
// using function pointers would carry a major performance cost.
type mac struct{ macGeneric }
func (h *mac) Write(p []byte) (int, error) {
nn := len(p)
if h.offset > 0 {
n := copy(h.buffer[h.offset:], p)
if h.offset+n < TagSize {
h.offset += n
return nn, nil
}
p = p[n:]
h.offset = 0
update(&h.macState, h.buffer[:])
}
if n := len(p) - (len(p) % TagSize); n > 0 {
update(&h.macState, p[:n])
p = p[n:]
}
if len(p) > 0 {
h.offset += copy(h.buffer[h.offset:], p)
}
return nn, nil
}
func (h *mac) Sum(out *[16]byte) {
state := h.macState
if h.offset > 0 {
update(&state, h.buffer[:h.offset])
}
finalize(out, &state.h, &state.s)
}

View File

@ -1,181 +0,0 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !gccgo,!purego
#include "textflag.h"
// This was ported from the amd64 implementation.
#define POLY1305_ADD(msg, h0, h1, h2, t0, t1, t2) \
MOVD (msg), t0; \
MOVD 8(msg), t1; \
MOVD $1, t2; \
ADDC t0, h0, h0; \
ADDE t1, h1, h1; \
ADDE t2, h2; \
ADD $16, msg
#define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3, t4, t5) \
MULLD r0, h0, t0; \
MULLD r0, h1, t4; \
MULHDU r0, h0, t1; \
MULHDU r0, h1, t5; \
ADDC t4, t1, t1; \
MULLD r0, h2, t2; \
ADDZE t5; \
MULHDU r1, h0, t4; \
MULLD r1, h0, h0; \
ADD t5, t2, t2; \
ADDC h0, t1, t1; \
MULLD h2, r1, t3; \
ADDZE t4, h0; \
MULHDU r1, h1, t5; \
MULLD r1, h1, t4; \
ADDC t4, t2, t2; \
ADDE t5, t3, t3; \
ADDC h0, t2, t2; \
MOVD $-4, t4; \
MOVD t0, h0; \
MOVD t1, h1; \
ADDZE t3; \
ANDCC $3, t2, h2; \
AND t2, t4, t0; \
ADDC t0, h0, h0; \
ADDE t3, h1, h1; \
SLD $62, t3, t4; \
SRD $2, t2; \
ADDZE h2; \
OR t4, t2, t2; \
SRD $2, t3; \
ADDC t2, h0, h0; \
ADDE t3, h1, h1; \
ADDZE h2
DATA ·poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF
DATA ·poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC
GLOBL ·poly1305Mask<>(SB), RODATA, $16
// func update(state *[7]uint64, msg []byte)
TEXT ·update(SB), $0-32
MOVD state+0(FP), R3
MOVD msg_base+8(FP), R4
MOVD msg_len+16(FP), R5
MOVD 0(R3), R8 // h0
MOVD 8(R3), R9 // h1
MOVD 16(R3), R10 // h2
MOVD 24(R3), R11 // r0
MOVD 32(R3), R12 // r1
CMP R5, $16
BLT bytes_between_0_and_15
loop:
POLY1305_ADD(R4, R8, R9, R10, R20, R21, R22)
multiply:
POLY1305_MUL(R8, R9, R10, R11, R12, R16, R17, R18, R14, R20, R21)
ADD $-16, R5
CMP R5, $16
BGE loop
bytes_between_0_and_15:
CMP $0, R5
BEQ done
MOVD $0, R16 // h0
MOVD $0, R17 // h1
flush_buffer:
CMP R5, $8
BLE just1
MOVD $8, R21
SUB R21, R5, R21
// Greater than 8 -- load the rightmost remaining bytes in msg
// and put into R17 (h1)
MOVD (R4)(R21), R17
MOVD $16, R22
// Find the offset to those bytes
SUB R5, R22, R22
SLD $3, R22
// Shift to get only the bytes in msg
SRD R22, R17, R17
// Put 1 at high end
MOVD $1, R23
SLD $3, R21
SLD R21, R23, R23
OR R23, R17, R17
// Remainder is 8
MOVD $8, R5
just1:
CMP R5, $8
BLT less8
// Exactly 8
MOVD (R4), R16
CMP $0, R17
// Check if we've already set R17; if not
// set 1 to indicate end of msg.
BNE carry
MOVD $1, R17
BR carry
less8:
MOVD $0, R16 // h0
MOVD $0, R22 // shift count
CMP R5, $4
BLT less4
MOVWZ (R4), R16
ADD $4, R4
ADD $-4, R5
MOVD $32, R22
less4:
CMP R5, $2
BLT less2
MOVHZ (R4), R21
SLD R22, R21, R21
OR R16, R21, R16
ADD $16, R22
ADD $-2, R5
ADD $2, R4
less2:
CMP $0, R5
BEQ insert1
MOVBZ (R4), R21
SLD R22, R21, R21
OR R16, R21, R16
ADD $8, R22
insert1:
// Insert 1 at end of msg
MOVD $1, R21
SLD R22, R21, R21
OR R16, R21, R16
carry:
// Add new values to h0, h1, h2
ADDC R16, R8
ADDE R17, R9
ADDE $0, R10
MOVD $16, R5
ADD R5, R4
BR multiply
done:
// Save h0, h1, h2 in state
MOVD R8, 0(R3)
MOVD R9, 8(R3)
MOVD R10, 16(R3)
RET

View File

@ -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,!purego // +build s390x,go1.11,!gccgo,!appengine
package poly1305 package poly1305
@ -10,66 +10,33 @@ import (
"golang.org/x/sys/cpu" "golang.org/x/sys/cpu"
) )
// updateVX is an assembly implementation of Poly1305 that uses vector // poly1305vx is an assembly implementation of Poly1305 that uses vector
// instructions. It must only be called if the vector facility (vx) is // instructions. It must only be called if the vector facility (vx) is
// available. // available.
//go:noescape //go:noescape
func updateVX(state *macState, msg []byte) func poly1305vx(out *[16]byte, m *byte, mlen uint64, key *[32]byte)
// mac is a replacement for macGeneric that uses a larger buffer and redirects // poly1305vmsl is an assembly implementation of Poly1305 that uses vector
// calls that would have gone to updateGeneric to updateVX if the vector // instructions, including VMSL. It must only be called if the vector facility (vx) is
// facility is installed. // available and if VMSL is supported.
// //go:noescape
// A larger buffer is required for good performance because the vector func poly1305vmsl(out *[16]byte, m *byte, mlen uint64, key *[32]byte)
// implementation has a higher fixed cost per call than the generic
// implementation.
type mac struct {
macState
buffer [16 * TagSize]byte // size must be a multiple of block size (16) // Sum generates an authenticator for m using a one-time key and puts the
offset int // 16-byte result into out. Authenticating two different messages with the same
} // key allows an attacker to forge messages at will.
func Sum(out *[16]byte, m []byte, key *[32]byte) {
func (h *mac) Write(p []byte) (int, error) { if cpu.S390X.HasVX {
nn := len(p) var mPtr *byte
if h.offset > 0 { if len(m) > 0 {
n := copy(h.buffer[h.offset:], p) mPtr = &m[0]
if h.offset+n < len(h.buffer) {
h.offset += n
return nn, nil
} }
p = p[n:] if cpu.S390X.HasVXE && len(m) > 256 {
h.offset = 0 poly1305vmsl(out, mPtr, uint64(len(m)), key)
if cpu.S390X.HasVX {
updateVX(&h.macState, h.buffer[:])
} else { } else {
updateGeneric(&h.macState, h.buffer[:]) poly1305vx(out, mPtr, uint64(len(m)), key)
} }
} else {
sumGeneric(out, m, key)
} }
tail := len(p) % len(h.buffer) // number of bytes to copy into buffer
body := len(p) - tail // number of bytes to process now
if body > 0 {
if cpu.S390X.HasVX {
updateVX(&h.macState, p[:body])
} else {
updateGeneric(&h.macState, p[:body])
}
}
h.offset = copy(h.buffer[:], p[body:]) // copy tail bytes - can be 0
return nn, nil
}
func (h *mac) Sum(out *[TagSize]byte) {
state := h.macState
remainder := h.buffer[:h.offset]
// Use the generic implementation if we have 2 or fewer blocks left
// to sum. The vector implementation has a higher startup time.
if cpu.S390X.HasVX && len(remainder) > 2*TagSize {
updateVX(&state, remainder)
} else if len(remainder) > 0 {
updateGeneric(&state, remainder)
}
finalize(out, &state.h, &state.s)
} }

View File

@ -2,187 +2,115 @@
// 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,!purego // +build s390x,go1.11,!gccgo,!appengine
#include "textflag.h" #include "textflag.h"
// This implementation of Poly1305 uses the vector facility (vx) // Implementation of Poly1305 using the vector facility (vx).
// to process up to 2 blocks (32 bytes) per iteration using an
// algorithm based on the one described in:
//
// NEON crypto, Daniel J. Bernstein & Peter Schwabe
// https://cryptojedi.org/papers/neoncrypto-20120320.pdf
//
// This algorithm uses 5 26-bit limbs to represent a 130-bit
// value. These limbs are, for the most part, zero extended and
// placed into 64-bit vector register elements. Each vector
// register is 128-bits wide and so holds 2 of these elements.
// Using 26-bit limbs allows us plenty of headroom to accomodate
// accumulations before and after multiplication without
// overflowing either 32-bits (before multiplication) or 64-bits
// (after multiplication).
//
// In order to parallelise the operations required to calculate
// the sum we use two separate accumulators and then sum those
// in an extra final step. For compatibility with the generic
// implementation we perform this summation at the end of every
// updateVX call.
//
// To use two accumulators we must multiply the message blocks
// by r² rather than r. Only the final message block should be
// multiplied by r.
//
// Example:
//
// We want to calculate the sum (h) for a 64 byte message (m):
//
// h = m[0:16]r + m[16:32]r³ + m[32:48]r² + m[48:64]r
//
// To do this we split the calculation into the even indices
// and odd indices of the message. These form our SIMD 'lanes':
//
// h = m[ 0:16]r + m[32:48]r² + <- lane 0
// m[16:32]r³ + m[48:64]r <- lane 1
//
// To calculate this iteratively we refactor so that both lanes
// are written in terms of r² and r:
//
// h = (m[ 0:16]r² + m[32:48])r² + <- lane 0
// (m[16:32]r² + m[48:64])r <- lane 1
// ^ ^
// | coefficients for second iteration
// coefficients for first iteration
//
// So in this case we would have two iterations. In the first
// both lanes are multiplied by r². In the second only the
// first lane is multiplied by r² and the second lane is
// instead multiplied by r. This gives use the odd and even
// powers of r that we need from the original equation.
//
// Notation:
//
// h - accumulator
// r - key
// m - message
//
// [a, b] - SIMD register holding two 64-bit values
// [a, b, c, d] - SIMD register holding four 32-bit values
// x[n] - limb n of variable x with bit width i
//
// Limbs are expressed in little endian order, so for 26-bit
// limbs x[4] will be the most significant limb and x[0]
// will be the least significant limb.
// masking constants // constants
#define MOD24 V0 // [0x0000000000ffffff, 0x0000000000ffffff] - mask low 24-bits #define MOD26 V0
#define MOD26 V1 // [0x0000000003ffffff, 0x0000000003ffffff] - mask low 26-bits #define EX0 V1
#define EX1 V2
#define EX2 V3
// expansion constants (see EXPAND macro) // temporaries
#define EX0 V2 #define T_0 V4
#define EX1 V3 #define T_1 V5
#define EX2 V4 #define T_2 V6
#define T_3 V7
#define T_4 V8
// key (r², r or 1 depending on context) // key (r)
#define R_0 V5 #define R_0 V9
#define R_1 V6 #define R_1 V10
#define R_2 V7 #define R_2 V11
#define R_3 V8 #define R_3 V12
#define R_4 V9 #define R_4 V13
#define R5_1 V14
#define R5_2 V15
#define R5_3 V16
#define R5_4 V17
#define RSAVE_0 R5
#define RSAVE_1 R6
#define RSAVE_2 R7
#define RSAVE_3 R8
#define RSAVE_4 R9
#define R5SAVE_1 V28
#define R5SAVE_2 V29
#define R5SAVE_3 V30
#define R5SAVE_4 V31
// precalculated coefficients (5r², 5r or 0 depending on context) // message block
#define R5_1 V10 #define F_0 V18
#define R5_2 V11 #define F_1 V19
#define R5_3 V12 #define F_2 V20
#define R5_4 V13 #define F_3 V21
#define F_4 V22
// message block (m) // accumulator
#define M_0 V14 #define H_0 V23
#define M_1 V15 #define H_1 V24
#define M_2 V16 #define H_2 V25
#define M_3 V17 #define H_3 V26
#define M_4 V18 #define H_4 V27
// accumulator (h) GLOBL ·keyMask<>(SB), RODATA, $16
#define H_0 V19 DATA ·keyMask<>+0(SB)/8, $0xffffff0ffcffff0f
#define H_1 V20 DATA ·keyMask<>+8(SB)/8, $0xfcffff0ffcffff0f
#define H_2 V21
#define H_3 V22
#define H_4 V23
// temporary registers (for short-lived values) GLOBL ·bswapMask<>(SB), RODATA, $16
#define T_0 V24 DATA ·bswapMask<>+0(SB)/8, $0x0f0e0d0c0b0a0908
#define T_1 V25 DATA ·bswapMask<>+8(SB)/8, $0x0706050403020100
#define T_2 V26
#define T_3 V27
#define T_4 V28
GLOBL ·constants<>(SB), RODATA, $0x30 GLOBL ·constants<>(SB), RODATA, $64
// MOD26
DATA ·constants<>+0(SB)/8, $0x3ffffff
DATA ·constants<>+8(SB)/8, $0x3ffffff
// EX0 // EX0
DATA ·constants<>+0x00(SB)/8, $0x0006050403020100 DATA ·constants<>+16(SB)/8, $0x0006050403020100
DATA ·constants<>+0x08(SB)/8, $0x1016151413121110 DATA ·constants<>+24(SB)/8, $0x1016151413121110
// EX1 // EX1
DATA ·constants<>+0x10(SB)/8, $0x060c0b0a09080706 DATA ·constants<>+32(SB)/8, $0x060c0b0a09080706
DATA ·constants<>+0x18(SB)/8, $0x161c1b1a19181716 DATA ·constants<>+40(SB)/8, $0x161c1b1a19181716
// EX2 // EX2
DATA ·constants<>+0x20(SB)/8, $0x0d0d0d0d0d0f0e0d DATA ·constants<>+48(SB)/8, $0x0d0d0d0d0d0f0e0d
DATA ·constants<>+0x28(SB)/8, $0x1d1d1d1d1d1f1e1d DATA ·constants<>+56(SB)/8, $0x1d1d1d1d1d1f1e1d
// MULTIPLY multiplies each lane of f and g, partially reduced // h = (f*g) % (2**130-5) [partial reduction]
// modulo 2¹³ - 5. The result, h, consists of partial products
// in each lane that need to be reduced further to produce the
// final result.
//
// h = (fg) % 2¹³ + (5fg) / 2¹³
//
// Note that the multiplication by 5 of the high bits is
// achieved by precalculating the multiplication of four of the
// g coefficients by 5. These are g51-g54.
#define MULTIPLY(f0, f1, f2, f3, f4, g0, g1, g2, g3, g4, g51, g52, g53, g54, h0, h1, h2, h3, h4) \ #define MULTIPLY(f0, f1, f2, f3, f4, g0, g1, g2, g3, g4, g51, g52, g53, g54, h0, h1, h2, h3, h4) \
VMLOF f0, g0, h0 \ VMLOF f0, g0, h0 \
VMLOF f0, g3, h3 \
VMLOF f0, g1, h1 \ VMLOF f0, g1, h1 \
VMLOF f0, g4, h4 \
VMLOF f0, g2, h2 \ VMLOF f0, g2, h2 \
VMLOF f0, g3, h3 \
VMLOF f0, g4, h4 \
VMLOF f1, g54, T_0 \ VMLOF f1, g54, T_0 \
VMLOF f1, g2, T_3 \
VMLOF f1, g0, T_1 \ VMLOF f1, g0, T_1 \
VMLOF f1, g3, T_4 \
VMLOF f1, g1, T_2 \ VMLOF f1, g1, T_2 \
VMLOF f1, g2, T_3 \
VMLOF f1, g3, T_4 \
VMALOF f2, g53, h0, h0 \ VMALOF f2, g53, h0, h0 \
VMALOF f2, g1, h3, h3 \
VMALOF f2, g54, h1, h1 \ VMALOF f2, g54, h1, h1 \
VMALOF f2, g2, h4, h4 \
VMALOF f2, g0, h2, h2 \ VMALOF f2, g0, h2, h2 \
VMALOF f2, g1, h3, h3 \
VMALOF f2, g2, h4, h4 \
VMALOF f3, g52, T_0, T_0 \ VMALOF f3, g52, T_0, T_0 \
VMALOF f3, g0, T_3, T_3 \
VMALOF f3, g53, T_1, T_1 \ VMALOF f3, g53, T_1, T_1 \
VMALOF f3, g1, T_4, T_4 \
VMALOF f3, g54, T_2, T_2 \ VMALOF f3, g54, T_2, T_2 \
VMALOF f3, g0, T_3, T_3 \
VMALOF f3, g1, T_4, T_4 \
VMALOF f4, g51, h0, h0 \ VMALOF f4, g51, h0, h0 \
VMALOF f4, g54, h3, h3 \
VMALOF f4, g52, h1, h1 \ VMALOF f4, g52, h1, h1 \
VMALOF f4, g0, h4, h4 \
VMALOF f4, g53, h2, h2 \ VMALOF f4, g53, h2, h2 \
VMALOF f4, g54, h3, h3 \
VMALOF f4, g0, h4, h4 \
VAG T_0, h0, h0 \ VAG T_0, h0, h0 \
VAG T_3, h3, h3 \
VAG T_1, h1, h1 \ VAG T_1, h1, h1 \
VAG T_4, h4, h4 \ VAG T_2, h2, h2 \
VAG T_2, h2, h2 VAG T_3, h3, h3 \
VAG T_4, h4, h4
// REDUCE performs the following carry operations in four // carry h0->h1 h3->h4, h1->h2 h4->h0, h0->h1 h2->h3, h3->h4
// stages, as specified in Bernstein & Schwabe:
//
// 1: h[0]->h[1] h[3]->h[4]
// 2: h[1]->h[2] h[4]->h[0]
// 3: h[0]->h[1] h[2]->h[3]
// 4: h[3]->h[4]
//
// The result is that all of the limbs are limited to 26-bits
// except for h[1] and h[4] which are limited to 27-bits.
//
// Note that although each limb is aligned at 26-bit intervals
// they may contain values that exceed 2² - 1, hence the need
// to carry the excess bits in each limb.
#define REDUCE(h0, h1, h2, h3, h4) \ #define REDUCE(h0, h1, h2, h3, h4) \
VESRLG $26, h0, T_0 \ VESRLG $26, h0, T_0 \
VESRLG $26, h3, T_1 \ VESRLG $26, h3, T_1 \
@ -208,155 +136,144 @@ DATA ·constants<>+0x28(SB)/8, $0x1d1d1d1d1d1f1e1d
VN MOD26, h3, h3 \ VN MOD26, h3, h3 \
VAG T_2, h4, h4 VAG T_2, h4, h4
// EXPAND splits the 128-bit little-endian values in0 and in1 // expand in0 into d[0] and in1 into d[1]
// into 26-bit big-endian limbs and places the results into
// the first and second lane of d[0:4] respectively.
//
// The EX0, EX1 and EX2 constants are arrays of byte indices
// for permutation. The permutation both reverses the bytes
// in the input and ensures the bytes are copied into the
// destination limb ready to be shifted into their final
// position.
#define EXPAND(in0, in1, d0, d1, d2, d3, d4) \ #define EXPAND(in0, in1, d0, d1, d2, d3, d4) \
VGBM $0x0707, d1 \ // d1=tmp
VPERM in0, in1, EX2, d4 \
VPERM in0, in1, EX0, d0 \ VPERM in0, in1, EX0, d0 \
VPERM in0, in1, EX1, d2 \ VPERM in0, in1, EX1, d2 \
VPERM in0, in1, EX2, d4 \ VN d1, d4, d4 \
VESRLG $26, d0, d1 \ VESRLG $26, d0, d1 \
VESRLG $30, d2, d3 \ VESRLG $30, d2, d3 \
VESRLG $4, d2, d2 \ VESRLG $4, d2, d2 \
VN MOD26, d0, d0 \ // [in0[0], in1[0]] VN MOD26, d0, d0 \
VN MOD26, d3, d3 \ // [in0[3], in1[3]] VN MOD26, d1, d1 \
VN MOD26, d1, d1 \ // [in0[1], in1[1]] VN MOD26, d2, d2 \
VN MOD24, d4, d4 \ // [in0[4], in1[4]] VN MOD26, d3, d3
VN MOD26, d2, d2 // [in0[2], in1[2]]
// func updateVX(state *macState, msg []byte) // pack h4:h0 into h1:h0 (no carry)
TEXT ·updateVX(SB), NOSPLIT, $0 #define PACK(h0, h1, h2, h3, h4) \
MOVD state+0(FP), R1 VESLG $26, h1, h1 \
LMG msg+8(FP), R2, R3 // R2=msg_base, R3=msg_len VESLG $26, h3, h3 \
VO h0, h1, h0 \
VO h2, h3, h2 \
VESLG $4, h2, h2 \
VLEIB $7, $48, h1 \
VSLB h1, h2, h2 \
VO h0, h2, h0 \
VLEIB $7, $104, h1 \
VSLB h1, h4, h3 \
VO h3, h0, h0 \
VLEIB $7, $24, h1 \
VSRLB h1, h4, h1
// load EX0, EX1 and EX2 // if h > 2**130-5 then h -= 2**130-5
#define MOD(h0, h1, t0, t1, t2) \
VZERO t0 \
VLEIG $1, $5, t0 \
VACCQ h0, t0, t1 \
VAQ h0, t0, t0 \
VONE t2 \
VLEIG $1, $-4, t2 \
VAQ t2, t1, t1 \
VACCQ h1, t1, t1 \
VONE t2 \
VAQ t2, t1, t1 \
VN h0, t1, t2 \
VNC t0, t1, t1 \
VO t1, t2, h0
// func poly1305vx(out *[16]byte, m *byte, mlen uint64, key *[32]key)
TEXT ·poly1305vx(SB), $0-32
// This code processes up to 2 blocks (32 bytes) per iteration
// using the algorithm described in:
// NEON crypto, Daniel J. Bernstein & Peter Schwabe
// https://cryptojedi.org/papers/neoncrypto-20120320.pdf
LMG out+0(FP), R1, R4 // R1=out, R2=m, R3=mlen, R4=key
// load MOD26, EX0, EX1 and EX2
MOVD $·constants<>(SB), R5 MOVD $·constants<>(SB), R5
VLM (R5), EX0, EX2 VLM (R5), MOD26, EX2
// generate masks // setup r
VGMG $(64-24), $63, MOD24 // [0x00ffffff, 0x00ffffff] VL (R4), T_0
VGMG $(64-26), $63, MOD26 // [0x03ffffff, 0x03ffffff] MOVD $·keyMask<>(SB), R6
VL (R6), T_1
VN T_0, T_1, T_0
EXPAND(T_0, T_0, R_0, R_1, R_2, R_3, R_4)
// load h (accumulator) and r (key) from state // setup r*5
VZERO T_1 // [0, 0] VLEIG $0, $5, T_0
VL 0(R1), T_0 // [h[0], h[1]] VLEIG $1, $5, T_0
VLEG $0, 16(R1), T_1 // [h[2], 0]
VL 24(R1), T_2 // [r[0], r[1]]
VPDI $0, T_0, T_2, T_3 // [h[0], r[0]]
VPDI $5, T_0, T_2, T_4 // [h[1], r[1]]
// unpack h and r into 26-bit limbs // store r (for final block)
// note: h[2] may have the low 3 bits set, so h[4] is a 27-bit value VMLOF T_0, R_1, R5SAVE_1
VN MOD26, T_3, H_0 // [h[0], r[0]] VMLOF T_0, R_2, R5SAVE_2
VZERO H_1 // [0, 0] VMLOF T_0, R_3, R5SAVE_3
VZERO H_3 // [0, 0] VMLOF T_0, R_4, R5SAVE_4
VGMG $(64-12-14), $(63-12), T_0 // [0x03fff000, 0x03fff000] - 26-bit mask with low 12 bits masked out VLGVG $0, R_0, RSAVE_0
VESLG $24, T_1, T_1 // [h[2]<<24, 0] VLGVG $0, R_1, RSAVE_1
VERIMG $-26&63, T_3, MOD26, H_1 // [h[1], r[1]] VLGVG $0, R_2, RSAVE_2
VESRLG $+52&63, T_3, H_2 // [h[2], r[2]] - low 12 bits only VLGVG $0, R_3, RSAVE_3
VERIMG $-14&63, T_4, MOD26, H_3 // [h[1], r[1]] VLGVG $0, R_4, RSAVE_4
VESRLG $40, T_4, H_4 // [h[4], r[4]] - low 24 bits only
VERIMG $+12&63, T_4, T_0, H_2 // [h[2], r[2]] - complete
VO T_1, H_4, H_4 // [h[4], r[4]] - complete
// replicate r across all 4 vector elements // skip r**2 calculation
VREPF $3, H_0, R_0 // [r[0], r[0], r[0], r[0]]
VREPF $3, H_1, R_1 // [r[1], r[1], r[1], r[1]]
VREPF $3, H_2, R_2 // [r[2], r[2], r[2], r[2]]
VREPF $3, H_3, R_3 // [r[3], r[3], r[3], r[3]]
VREPF $3, H_4, R_4 // [r[4], r[4], r[4], r[4]]
// zero out lane 1 of h
VLEIG $1, $0, H_0 // [h[0], 0]
VLEIG $1, $0, H_1 // [h[1], 0]
VLEIG $1, $0, H_2 // [h[2], 0]
VLEIG $1, $0, H_3 // [h[3], 0]
VLEIG $1, $0, H_4 // [h[4], 0]
// calculate 5r (ignore least significant limb)
VREPIF $5, T_0
VMLF T_0, R_1, R5_1 // [5r[1], 5r[1], 5r[1], 5r[1]]
VMLF T_0, R_2, R5_2 // [5r[2], 5r[2], 5r[2], 5r[2]]
VMLF T_0, R_3, R5_3 // [5r[3], 5r[3], 5r[3], 5r[3]]
VMLF T_0, R_4, R5_4 // [5r[4], 5r[4], 5r[4], 5r[4]]
// skip r² calculation if we are only calculating one block
CMPBLE R3, $16, skip CMPBLE R3, $16, skip
// calculate r² // calculate r**2
MULTIPLY(R_0, R_1, R_2, R_3, R_4, R_0, R_1, R_2, R_3, R_4, R5_1, R5_2, R5_3, R5_4, M_0, M_1, M_2, M_3, M_4) MULTIPLY(R_0, R_1, R_2, R_3, R_4, R_0, R_1, R_2, R_3, R_4, R5SAVE_1, R5SAVE_2, R5SAVE_3, R5SAVE_4, H_0, H_1, H_2, H_3, H_4)
REDUCE(M_0, M_1, M_2, M_3, M_4) REDUCE(H_0, H_1, H_2, H_3, H_4)
VGBM $0x0f0f, T_0 VLEIG $0, $5, T_0
VERIMG $0, M_0, T_0, R_0 // [r[0], r²[0], r[0], r²[0]] VLEIG $1, $5, T_0
VERIMG $0, M_1, T_0, R_1 // [r[1], r²[1], r[1], r²[1]] VMLOF T_0, H_1, R5_1
VERIMG $0, M_2, T_0, R_2 // [r[2], r²[2], r[2], r²[2]] VMLOF T_0, H_2, R5_2
VERIMG $0, M_3, T_0, R_3 // [r[3], r²[3], r[3], r²[3]] VMLOF T_0, H_3, R5_3
VERIMG $0, M_4, T_0, R_4 // [r[4], r²[4], r[4], r²[4]] VMLOF T_0, H_4, R5_4
VLR H_0, R_0
VLR H_1, R_1
VLR H_2, R_2
VLR H_3, R_3
VLR H_4, R_4
// calculate 5r² (ignore least significant limb) // initialize h
VREPIF $5, T_0 VZERO H_0
VMLF T_0, R_1, R5_1 // [5r[1], 5r²[1], 5r[1], 5r²[1]] VZERO H_1
VMLF T_0, R_2, R5_2 // [5r[2], 5r²[2], 5r[2], 5r²[2]] VZERO H_2
VMLF T_0, R_3, R5_3 // [5r[3], 5r²[3], 5r[3], 5r²[3]] VZERO H_3
VMLF T_0, R_4, R5_4 // [5r[4], 5r²[4], 5r[4], 5r²[4]] VZERO H_4
loop: loop:
CMPBLE R3, $32, b2 // 2 or fewer blocks remaining, need to change key coefficients CMPBLE R3, $32, b2
VLM (R2), T_0, T_1
// load next 2 blocks from message SUB $32, R3
VLM (R2), T_0, T_1 MOVD $32(R2), R2
EXPAND(T_0, T_1, F_0, F_1, F_2, F_3, F_4)
// update message slice VLEIB $4, $1, F_4
SUB $32, R3 VLEIB $12, $1, F_4
MOVD $32(R2), R2
// unpack message blocks into 26-bit big-endian limbs
EXPAND(T_0, T_1, M_0, M_1, M_2, M_3, M_4)
// add 2¹² to each message block value
VLEIB $4, $1, M_4
VLEIB $12, $1, M_4
multiply: multiply:
// accumulate the incoming message VAG H_0, F_0, F_0
VAG H_0, M_0, M_0 VAG H_1, F_1, F_1
VAG H_3, M_3, M_3 VAG H_2, F_2, F_2
VAG H_1, M_1, M_1 VAG H_3, F_3, F_3
VAG H_4, M_4, M_4 VAG H_4, F_4, F_4
VAG H_2, M_2, M_2 MULTIPLY(F_0, F_1, F_2, F_3, F_4, R_0, R_1, R_2, R_3, R_4, R5_1, R5_2, R5_3, R5_4, H_0, H_1, H_2, H_3, H_4)
// multiply the accumulator by the key coefficient
MULTIPLY(M_0, M_1, M_2, M_3, M_4, R_0, R_1, R_2, R_3, R_4, R5_1, R5_2, R5_3, R5_4, H_0, H_1, H_2, H_3, H_4)
// carry and partially reduce the partial products
REDUCE(H_0, H_1, H_2, H_3, H_4) REDUCE(H_0, H_1, H_2, H_3, H_4)
CMPBNE R3, $0, loop CMPBNE R3, $0, loop
finish: finish:
// sum lane 0 and lane 1 and put the result in lane 1 // sum vectors
VZERO T_0 VZERO T_0
VSUMQG H_0, T_0, H_0 VSUMQG H_0, T_0, H_0
VSUMQG H_3, T_0, H_3
VSUMQG H_1, T_0, H_1 VSUMQG H_1, T_0, H_1
VSUMQG H_4, T_0, H_4
VSUMQG H_2, T_0, H_2 VSUMQG H_2, T_0, H_2
VSUMQG H_3, T_0, H_3
VSUMQG H_4, T_0, H_4
// reduce again after summation // h may be >= 2*(2**130-5) so we need to reduce it again
// TODO(mundaym): there might be a more efficient way to do this
// now that we only have 1 active lane. For example, we could
// simultaneously pack the values as we reduce them.
REDUCE(H_0, H_1, H_2, H_3, H_4) REDUCE(H_0, H_1, H_2, H_3, H_4)
// carry h[1] through to h[4] so that only h[4] can exceed 2² - 1 // carry h1->h4
// TODO(mundaym): in testing this final carry was unnecessary.
// Needs a proof before it can be removed though.
VESRLG $26, H_1, T_1 VESRLG $26, H_1, T_1
VN MOD26, H_1, H_1 VN MOD26, H_1, H_1
VAQ T_1, H_2, H_2 VAQ T_1, H_2, H_2
@ -367,137 +284,95 @@ finish:
VN MOD26, H_3, H_3 VN MOD26, H_3, H_3
VAQ T_3, H_4, H_4 VAQ T_3, H_4, H_4
// h is now < 2(2¹³ - 5) // h is now < 2*(2**130-5)
// Pack each lane in h[0:4] into h[0:1]. // pack h into h1 (hi) and h0 (lo)
VESLG $26, H_1, H_1 PACK(H_0, H_1, H_2, H_3, H_4)
VESLG $26, H_3, H_3
VO H_0, H_1, H_0 // if h > 2**130-5 then h -= 2**130-5
VO H_2, H_3, H_2 MOD(H_0, H_1, T_0, T_1, T_2)
VESLG $4, H_2, H_2
VLEIB $7, $48, H_1 // h += s
VSLB H_1, H_2, H_2 MOVD $·bswapMask<>(SB), R5
VO H_0, H_2, H_0 VL (R5), T_1
VLEIB $7, $104, H_1 VL 16(R4), T_0
VSLB H_1, H_4, H_3 VPERM T_0, T_0, T_1, T_0 // reverse bytes (to big)
VO H_3, H_0, H_0 VAQ T_0, H_0, H_0
VLEIB $7, $24, H_1 VPERM H_0, H_0, T_1, H_0 // reverse bytes (to little)
VSRLB H_1, H_4, H_1 VST H_0, (R1)
// update state
VSTEG $1, H_0, 0(R1)
VSTEG $0, H_0, 8(R1)
VSTEG $1, H_1, 16(R1)
RET RET
b2: // 2 or fewer blocks remaining b2:
CMPBLE R3, $16, b1 CMPBLE R3, $16, b1
// Load the 2 remaining blocks (17-32 bytes remaining). // 2 blocks remaining
MOVD $-17(R3), R0 // index of final byte to load modulo 16 SUB $17, R3
VL (R2), T_0 // load full 16 byte block VL (R2), T_0
VLL R0, 16(R2), T_1 // load final (possibly partial) block and pad with zeros to 16 bytes VLL R3, 16(R2), T_1
ADD $1, R3
// The Poly1305 algorithm requires that a 1 bit be appended to
// each message block. If the final block is less than 16 bytes
// long then it is easiest to insert the 1 before the message
// block is split into 26-bit limbs. If, on the other hand, the
// final message block is 16 bytes long then we append the 1 bit
// after expansion as normal.
MOVBZ $1, R0 MOVBZ $1, R0
MOVD $-16(R3), R3 // index of byte in last block to insert 1 at (could be 16) CMPBEQ R3, $16, 2(PC)
CMPBEQ R3, $16, 2(PC) // skip the insertion if the final block is 16 bytes long VLVGB R3, R0, T_1
VLVGB R3, R0, T_1 // insert 1 into the byte at index R3 EXPAND(T_0, T_1, F_0, F_1, F_2, F_3, F_4)
// Split both blocks into 26-bit limbs in the appropriate lanes.
EXPAND(T_0, T_1, M_0, M_1, M_2, M_3, M_4)
// Append a 1 byte to the end of the second to last block.
VLEIB $4, $1, M_4
// Append a 1 byte to the end of the last block only if it is a
// full 16 byte block.
CMPBNE R3, $16, 2(PC) CMPBNE R3, $16, 2(PC)
VLEIB $12, $1, M_4 VLEIB $12, $1, F_4
VLEIB $4, $1, F_4
// Finally, set up the coefficients for the final multiplication. // setup [r²,r]
// We have previously saved r and 5r in the 32-bit even indexes VLVGG $1, RSAVE_0, R_0
// of the R_[0-4] and R5_[1-4] coefficient registers. VLVGG $1, RSAVE_1, R_1
// VLVGG $1, RSAVE_2, R_2
// We want lane 0 to be multiplied by r² so that can be kept the VLVGG $1, RSAVE_3, R_3
// same. We want lane 1 to be multiplied by r so we need to move VLVGG $1, RSAVE_4, R_4
// the saved r value into the 32-bit odd index in lane 1 by VPDI $0, R5_1, R5SAVE_1, R5_1
// rotating the 64-bit lane by 32. VPDI $0, R5_2, R5SAVE_2, R5_2
VGBM $0x00ff, T_0 // [0, 0xffffffffffffffff] - mask lane 1 only VPDI $0, R5_3, R5SAVE_3, R5_3
VERIMG $32, R_0, T_0, R_0 // [_, r²[0], _, r[0]] VPDI $0, R5_4, R5SAVE_4, R5_4
VERIMG $32, R_1, T_0, R_1 // [_, r²[1], _, r[1]]
VERIMG $32, R_2, T_0, R_2 // [_, r²[2], _, r[2]]
VERIMG $32, R_3, T_0, R_3 // [_, r²[3], _, r[3]]
VERIMG $32, R_4, T_0, R_4 // [_, r²[4], _, r[4]]
VERIMG $32, R5_1, T_0, R5_1 // [_, 5r²[1], _, 5r[1]]
VERIMG $32, R5_2, T_0, R5_2 // [_, 5r²[2], _, 5r[2]]
VERIMG $32, R5_3, T_0, R5_3 // [_, 5r²[3], _, 5r[3]]
VERIMG $32, R5_4, T_0, R5_4 // [_, 5r²[4], _, 5r[4]]
MOVD $0, R3 MOVD $0, R3
BR multiply BR multiply
skip: skip:
VZERO H_0
VZERO H_1
VZERO H_2
VZERO H_3
VZERO H_4
CMPBEQ R3, $0, finish CMPBEQ R3, $0, finish
b1: // 1 block remaining b1:
// 1 block remaining
// Load the final block (1-16 bytes). This will be placed into SUB $1, R3
// lane 0. VLL R3, (R2), T_0
MOVD $-1(R3), R0 ADD $1, R3
VLL R0, (R2), T_0 // pad to 16 bytes with zeros
// The Poly1305 algorithm requires that a 1 bit be appended to
// each message block. If the final block is less than 16 bytes
// long then it is easiest to insert the 1 before the message
// block is split into 26-bit limbs. If, on the other hand, the
// final message block is 16 bytes long then we append the 1 bit
// after expansion as normal.
MOVBZ $1, R0 MOVBZ $1, R0
CMPBEQ R3, $16, 2(PC) CMPBEQ R3, $16, 2(PC)
VLVGB R3, R0, T_0 VLVGB R3, R0, T_0
VZERO T_1
// Set the message block in lane 1 to the value 0 so that it EXPAND(T_0, T_1, F_0, F_1, F_2, F_3, F_4)
// can be accumulated without affecting the final result.
VZERO T_1
// Split the final message block into 26-bit limbs in lane 0.
// Lane 1 will be contain 0.
EXPAND(T_0, T_1, M_0, M_1, M_2, M_3, M_4)
// Append a 1 byte to the end of the last block only if it is a
// full 16 byte block.
CMPBNE R3, $16, 2(PC) CMPBNE R3, $16, 2(PC)
VLEIB $4, $1, M_4 VLEIB $4, $1, F_4
VLEIG $1, $1, R_0
VZERO R_1
VZERO R_2
VZERO R_3
VZERO R_4
VZERO R5_1
VZERO R5_2
VZERO R5_3
VZERO R5_4
// We have previously saved r and 5r in the 32-bit even indexes // setup [r, 1]
// of the R_[0-4] and R5_[1-4] coefficient registers. VLVGG $0, RSAVE_0, R_0
// VLVGG $0, RSAVE_1, R_1
// We want lane 0 to be multiplied by r so we need to move the VLVGG $0, RSAVE_2, R_2
// saved r value into the 32-bit odd index in lane 0. We want VLVGG $0, RSAVE_3, R_3
// lane 1 to be set to the value 1. This makes multiplication VLVGG $0, RSAVE_4, R_4
// a no-op. We do this by setting lane 1 in every register to 0 VPDI $0, R5SAVE_1, R5_1, R5_1
// and then just setting the 32-bit index 3 in R_0 to 1. VPDI $0, R5SAVE_2, R5_2, R5_2
VZERO T_0 VPDI $0, R5SAVE_3, R5_3, R5_3
MOVD $0, R0 VPDI $0, R5SAVE_4, R5_4, R5_4
MOVD $0x10111213, R12
VLVGP R12, R0, T_1 // [_, 0x10111213, _, 0x00000000]
VPERM T_0, R_0, T_1, R_0 // [_, r[0], _, 0]
VPERM T_0, R_1, T_1, R_1 // [_, r[1], _, 0]
VPERM T_0, R_2, T_1, R_2 // [_, r[2], _, 0]
VPERM T_0, R_3, T_1, R_3 // [_, r[3], _, 0]
VPERM T_0, R_4, T_1, R_4 // [_, r[4], _, 0]
VPERM T_0, R5_1, T_1, R5_1 // [_, 5r[1], _, 0]
VPERM T_0, R5_2, T_1, R5_2 // [_, 5r[2], _, 0]
VPERM T_0, R5_3, T_1, R5_3 // [_, 5r[3], _, 0]
VPERM T_0, R5_4, T_1, R5_4 // [_, 5r[4], _, 0]
// Set the value of lane 1 to be 1.
VLEIF $3, $1, R_0 // [_, r[0], _, 1]
MOVD $0, R3 MOVD $0, R3
BR multiply BR multiply

909
vendor/golang.org/x/crypto/poly1305/sum_vmsl_s390x.s generated vendored Normal file
View File

@ -0,0 +1,909 @@
// 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 s390x,go1.11,!gccgo,!appengine
#include "textflag.h"
// Implementation of Poly1305 using the vector facility (vx) and the VMSL instruction.
// constants
#define EX0 V1
#define EX1 V2
#define EX2 V3
// temporaries
#define T_0 V4
#define T_1 V5
#define T_2 V6
#define T_3 V7
#define T_4 V8
#define T_5 V9
#define T_6 V10
#define T_7 V11
#define T_8 V12
#define T_9 V13
#define T_10 V14
// r**2 & r**4
#define R_0 V15
#define R_1 V16
#define R_2 V17
#define R5_1 V18
#define R5_2 V19
// key (r)
#define RSAVE_0 R7
#define RSAVE_1 R8
#define RSAVE_2 R9
#define R5SAVE_1 R10
#define R5SAVE_2 R11
// message block
#define M0 V20
#define M1 V21
#define M2 V22
#define M3 V23
#define M4 V24
#define M5 V25
// accumulator
#define H0_0 V26
#define H1_0 V27
#define H2_0 V28
#define H0_1 V29
#define H1_1 V30
#define H2_1 V31
GLOBL ·keyMask<>(SB), RODATA, $16
DATA ·keyMask<>+0(SB)/8, $0xffffff0ffcffff0f
DATA ·keyMask<>+8(SB)/8, $0xfcffff0ffcffff0f
GLOBL ·bswapMask<>(SB), RODATA, $16
DATA ·bswapMask<>+0(SB)/8, $0x0f0e0d0c0b0a0908
DATA ·bswapMask<>+8(SB)/8, $0x0706050403020100
GLOBL ·constants<>(SB), RODATA, $48
// EX0
DATA ·constants<>+0(SB)/8, $0x18191a1b1c1d1e1f
DATA ·constants<>+8(SB)/8, $0x0000050403020100
// EX1
DATA ·constants<>+16(SB)/8, $0x18191a1b1c1d1e1f
DATA ·constants<>+24(SB)/8, $0x00000a0908070605
// EX2
DATA ·constants<>+32(SB)/8, $0x18191a1b1c1d1e1f
DATA ·constants<>+40(SB)/8, $0x0000000f0e0d0c0b
GLOBL ·c<>(SB), RODATA, $48
// EX0
DATA ·c<>+0(SB)/8, $0x0000050403020100
DATA ·c<>+8(SB)/8, $0x0000151413121110
// EX1
DATA ·c<>+16(SB)/8, $0x00000a0908070605
DATA ·c<>+24(SB)/8, $0x00001a1918171615
// EX2
DATA ·c<>+32(SB)/8, $0x0000000f0e0d0c0b
DATA ·c<>+40(SB)/8, $0x0000001f1e1d1c1b
GLOBL ·reduce<>(SB), RODATA, $32
// 44 bit
DATA ·reduce<>+0(SB)/8, $0x0
DATA ·reduce<>+8(SB)/8, $0xfffffffffff
// 42 bit
DATA ·reduce<>+16(SB)/8, $0x0
DATA ·reduce<>+24(SB)/8, $0x3ffffffffff
// h = (f*g) % (2**130-5) [partial reduction]
// uses T_0...T_9 temporary registers
// input: m02_0, m02_1, m02_2, m13_0, m13_1, m13_2, r_0, r_1, r_2, r5_1, r5_2, m4_0, m4_1, m4_2, m5_0, m5_1, m5_2
// temp: t0, t1, t2, t3, t4, t5, t6, t7, t8, t9
// output: m02_0, m02_1, m02_2, m13_0, m13_1, m13_2
#define MULTIPLY(m02_0, m02_1, m02_2, m13_0, m13_1, m13_2, r_0, r_1, r_2, r5_1, r5_2, m4_0, m4_1, m4_2, m5_0, m5_1, m5_2, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9) \
\ // Eliminate the dependency for the last 2 VMSLs
VMSLG m02_0, r_2, m4_2, m4_2 \
VMSLG m13_0, r_2, m5_2, m5_2 \ // 8 VMSLs pipelined
VMSLG m02_0, r_0, m4_0, m4_0 \
VMSLG m02_1, r5_2, V0, T_0 \
VMSLG m02_0, r_1, m4_1, m4_1 \
VMSLG m02_1, r_0, V0, T_1 \
VMSLG m02_1, r_1, V0, T_2 \
VMSLG m02_2, r5_1, V0, T_3 \
VMSLG m02_2, r5_2, V0, T_4 \
VMSLG m13_0, r_0, m5_0, m5_0 \
VMSLG m13_1, r5_2, V0, T_5 \
VMSLG m13_0, r_1, m5_1, m5_1 \
VMSLG m13_1, r_0, V0, T_6 \
VMSLG m13_1, r_1, V0, T_7 \
VMSLG m13_2, r5_1, V0, T_8 \
VMSLG m13_2, r5_2, V0, T_9 \
VMSLG m02_2, r_0, m4_2, m4_2 \
VMSLG m13_2, r_0, m5_2, m5_2 \
VAQ m4_0, T_0, m02_0 \
VAQ m4_1, T_1, m02_1 \
VAQ m5_0, T_5, m13_0 \
VAQ m5_1, T_6, m13_1 \
VAQ m02_0, T_3, m02_0 \
VAQ m02_1, T_4, m02_1 \
VAQ m13_0, T_8, m13_0 \
VAQ m13_1, T_9, m13_1 \
VAQ m4_2, T_2, m02_2 \
VAQ m5_2, T_7, m13_2 \
// SQUARE uses three limbs of r and r_2*5 to output square of r
// uses T_1, T_5 and T_7 temporary registers
// input: r_0, r_1, r_2, r5_2
// temp: TEMP0, TEMP1, TEMP2
// output: p0, p1, p2
#define SQUARE(r_0, r_1, r_2, r5_2, p0, p1, p2, TEMP0, TEMP1, TEMP2) \
VMSLG r_0, r_0, p0, p0 \
VMSLG r_1, r5_2, V0, TEMP0 \
VMSLG r_2, r5_2, p1, p1 \
VMSLG r_0, r_1, V0, TEMP1 \
VMSLG r_1, r_1, p2, p2 \
VMSLG r_0, r_2, V0, TEMP2 \
VAQ TEMP0, p0, p0 \
VAQ TEMP1, p1, p1 \
VAQ TEMP2, p2, p2 \
VAQ TEMP0, p0, p0 \
VAQ TEMP1, p1, p1 \
VAQ TEMP2, p2, p2 \
// carry h0->h1->h2->h0 || h3->h4->h5->h3
// uses T_2, T_4, T_5, T_7, T_8, T_9
// t6, t7, t8, t9, t10, t11
// input: h0, h1, h2, h3, h4, h5
// temp: t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11
// output: h0, h1, h2, h3, h4, h5
#define REDUCE(h0, h1, h2, h3, h4, h5, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11) \
VLM (R12), t6, t7 \ // 44 and 42 bit clear mask
VLEIB $7, $0x28, t10 \ // 5 byte shift mask
VREPIB $4, t8 \ // 4 bit shift mask
VREPIB $2, t11 \ // 2 bit shift mask
VSRLB t10, h0, t0 \ // h0 byte shift
VSRLB t10, h1, t1 \ // h1 byte shift
VSRLB t10, h2, t2 \ // h2 byte shift
VSRLB t10, h3, t3 \ // h3 byte shift
VSRLB t10, h4, t4 \ // h4 byte shift
VSRLB t10, h5, t5 \ // h5 byte shift
VSRL t8, t0, t0 \ // h0 bit shift
VSRL t8, t1, t1 \ // h2 bit shift
VSRL t11, t2, t2 \ // h2 bit shift
VSRL t8, t3, t3 \ // h3 bit shift
VSRL t8, t4, t4 \ // h4 bit shift
VESLG $2, t2, t9 \ // h2 carry x5
VSRL t11, t5, t5 \ // h5 bit shift
VN t6, h0, h0 \ // h0 clear carry
VAQ t2, t9, t2 \ // h2 carry x5
VESLG $2, t5, t9 \ // h5 carry x5
VN t6, h1, h1 \ // h1 clear carry
VN t7, h2, h2 \ // h2 clear carry
VAQ t5, t9, t5 \ // h5 carry x5
VN t6, h3, h3 \ // h3 clear carry
VN t6, h4, h4 \ // h4 clear carry
VN t7, h5, h5 \ // h5 clear carry
VAQ t0, h1, h1 \ // h0->h1
VAQ t3, h4, h4 \ // h3->h4
VAQ t1, h2, h2 \ // h1->h2
VAQ t4, h5, h5 \ // h4->h5
VAQ t2, h0, h0 \ // h2->h0
VAQ t5, h3, h3 \ // h5->h3
VREPG $1, t6, t6 \ // 44 and 42 bit masks across both halves
VREPG $1, t7, t7 \
VSLDB $8, h0, h0, h0 \ // set up [h0/1/2, h3/4/5]
VSLDB $8, h1, h1, h1 \
VSLDB $8, h2, h2, h2 \
VO h0, h3, h3 \
VO h1, h4, h4 \
VO h2, h5, h5 \
VESRLG $44, h3, t0 \ // 44 bit shift right
VESRLG $44, h4, t1 \
VESRLG $42, h5, t2 \
VN t6, h3, h3 \ // clear carry bits
VN t6, h4, h4 \
VN t7, h5, h5 \
VESLG $2, t2, t9 \ // multiply carry by 5
VAQ t9, t2, t2 \
VAQ t0, h4, h4 \
VAQ t1, h5, h5 \
VAQ t2, h3, h3 \
// carry h0->h1->h2->h0
// input: h0, h1, h2
// temp: t0, t1, t2, t3, t4, t5, t6, t7, t8
// output: h0, h1, h2
#define REDUCE2(h0, h1, h2, t0, t1, t2, t3, t4, t5, t6, t7, t8) \
VLEIB $7, $0x28, t3 \ // 5 byte shift mask
VREPIB $4, t4 \ // 4 bit shift mask
VREPIB $2, t7 \ // 2 bit shift mask
VGBM $0x003F, t5 \ // mask to clear carry bits
VSRLB t3, h0, t0 \
VSRLB t3, h1, t1 \
VSRLB t3, h2, t2 \
VESRLG $4, t5, t5 \ // 44 bit clear mask
VSRL t4, t0, t0 \
VSRL t4, t1, t1 \
VSRL t7, t2, t2 \
VESRLG $2, t5, t6 \ // 42 bit clear mask
VESLG $2, t2, t8 \
VAQ t8, t2, t2 \
VN t5, h0, h0 \
VN t5, h1, h1 \
VN t6, h2, h2 \
VAQ t0, h1, h1 \
VAQ t1, h2, h2 \
VAQ t2, h0, h0 \
VSRLB t3, h0, t0 \
VSRLB t3, h1, t1 \
VSRLB t3, h2, t2 \
VSRL t4, t0, t0 \
VSRL t4, t1, t1 \
VSRL t7, t2, t2 \
VN t5, h0, h0 \
VN t5, h1, h1 \
VESLG $2, t2, t8 \
VN t6, h2, h2 \
VAQ t0, h1, h1 \
VAQ t8, t2, t2 \
VAQ t1, h2, h2 \
VAQ t2, h0, h0 \
// expands two message blocks into the lower halfs of the d registers
// moves the contents of the d registers into upper halfs
// input: in1, in2, d0, d1, d2, d3, d4, d5
// temp: TEMP0, TEMP1, TEMP2, TEMP3
// output: d0, d1, d2, d3, d4, d5
#define EXPACC(in1, in2, d0, d1, d2, d3, d4, d5, TEMP0, TEMP1, TEMP2, TEMP3) \
VGBM $0xff3f, TEMP0 \
VGBM $0xff1f, TEMP1 \
VESLG $4, d1, TEMP2 \
VESLG $4, d4, TEMP3 \
VESRLG $4, TEMP0, TEMP0 \
VPERM in1, d0, EX0, d0 \
VPERM in2, d3, EX0, d3 \
VPERM in1, d2, EX2, d2 \
VPERM in2, d5, EX2, d5 \
VPERM in1, TEMP2, EX1, d1 \
VPERM in2, TEMP3, EX1, d4 \
VN TEMP0, d0, d0 \
VN TEMP0, d3, d3 \
VESRLG $4, d1, d1 \
VESRLG $4, d4, d4 \
VN TEMP1, d2, d2 \
VN TEMP1, d5, d5 \
VN TEMP0, d1, d1 \
VN TEMP0, d4, d4 \
// expands one message block into the lower halfs of the d registers
// moves the contents of the d registers into upper halfs
// input: in, d0, d1, d2
// temp: TEMP0, TEMP1, TEMP2
// output: d0, d1, d2
#define EXPACC2(in, d0, d1, d2, TEMP0, TEMP1, TEMP2) \
VGBM $0xff3f, TEMP0 \
VESLG $4, d1, TEMP2 \
VGBM $0xff1f, TEMP1 \
VPERM in, d0, EX0, d0 \
VESRLG $4, TEMP0, TEMP0 \
VPERM in, d2, EX2, d2 \
VPERM in, TEMP2, EX1, d1 \
VN TEMP0, d0, d0 \
VN TEMP1, d2, d2 \
VESRLG $4, d1, d1 \
VN TEMP0, d1, d1 \
// pack h2:h0 into h1:h0 (no carry)
// input: h0, h1, h2
// output: h0, h1, h2
#define PACK(h0, h1, h2) \
VMRLG h1, h2, h2 \ // copy h1 to upper half h2
VESLG $44, h1, h1 \ // shift limb 1 44 bits, leaving 20
VO h0, h1, h0 \ // combine h0 with 20 bits from limb 1
VESRLG $20, h2, h1 \ // put top 24 bits of limb 1 into h1
VLEIG $1, $0, h1 \ // clear h2 stuff from lower half of h1
VO h0, h1, h0 \ // h0 now has 88 bits (limb 0 and 1)
VLEIG $0, $0, h2 \ // clear upper half of h2
VESRLG $40, h2, h1 \ // h1 now has upper two bits of result
VLEIB $7, $88, h1 \ // for byte shift (11 bytes)
VSLB h1, h2, h2 \ // shift h2 11 bytes to the left
VO h0, h2, h0 \ // combine h0 with 20 bits from limb 1
VLEIG $0, $0, h1 \ // clear upper half of h1
// if h > 2**130-5 then h -= 2**130-5
// input: h0, h1
// temp: t0, t1, t2
// output: h0
#define MOD(h0, h1, t0, t1, t2) \
VZERO t0 \
VLEIG $1, $5, t0 \
VACCQ h0, t0, t1 \
VAQ h0, t0, t0 \
VONE t2 \
VLEIG $1, $-4, t2 \
VAQ t2, t1, t1 \
VACCQ h1, t1, t1 \
VONE t2 \
VAQ t2, t1, t1 \
VN h0, t1, t2 \
VNC t0, t1, t1 \
VO t1, t2, h0 \
// func poly1305vmsl(out *[16]byte, m *byte, mlen uint64, key *[32]key)
TEXT ·poly1305vmsl(SB), $0-32
// This code processes 6 + up to 4 blocks (32 bytes) per iteration
// using the algorithm described in:
// NEON crypto, Daniel J. Bernstein & Peter Schwabe
// https://cryptojedi.org/papers/neoncrypto-20120320.pdf
// And as moddified for VMSL as described in
// Accelerating Poly1305 Cryptographic Message Authentication on the z14
// O'Farrell et al, CASCON 2017, p48-55
// https://ibm.ent.box.com/s/jf9gedj0e9d2vjctfyh186shaztavnht
LMG out+0(FP), R1, R4 // R1=out, R2=m, R3=mlen, R4=key
VZERO V0 // c
// load EX0, EX1 and EX2
MOVD $·constants<>(SB), R5
VLM (R5), EX0, EX2 // c
// setup r
VL (R4), T_0
MOVD $·keyMask<>(SB), R6
VL (R6), T_1
VN T_0, T_1, T_0
VZERO T_2 // limbs for r
VZERO T_3
VZERO T_4
EXPACC2(T_0, T_2, T_3, T_4, T_1, T_5, T_7)
// T_2, T_3, T_4: [0, r]
// setup r*20
VLEIG $0, $0, T_0
VLEIG $1, $20, T_0 // T_0: [0, 20]
VZERO T_5
VZERO T_6
VMSLG T_0, T_3, T_5, T_5
VMSLG T_0, T_4, T_6, T_6
// store r for final block in GR
VLGVG $1, T_2, RSAVE_0 // c
VLGVG $1, T_3, RSAVE_1 // c
VLGVG $1, T_4, RSAVE_2 // c
VLGVG $1, T_5, R5SAVE_1 // c
VLGVG $1, T_6, R5SAVE_2 // c
// initialize h
VZERO H0_0
VZERO H1_0
VZERO H2_0
VZERO H0_1
VZERO H1_1
VZERO H2_1
// initialize pointer for reduce constants
MOVD $·reduce<>(SB), R12
// calculate r**2 and 20*(r**2)
VZERO R_0
VZERO R_1
VZERO R_2
SQUARE(T_2, T_3, T_4, T_6, R_0, R_1, R_2, T_1, T_5, T_7)
REDUCE2(R_0, R_1, R_2, M0, M1, M2, M3, M4, R5_1, R5_2, M5, T_1)
VZERO R5_1
VZERO R5_2
VMSLG T_0, R_1, R5_1, R5_1
VMSLG T_0, R_2, R5_2, R5_2
// skip r**4 calculation if 3 blocks or less
CMPBLE R3, $48, b4
// calculate r**4 and 20*(r**4)
VZERO T_8
VZERO T_9
VZERO T_10
SQUARE(R_0, R_1, R_2, R5_2, T_8, T_9, T_10, T_1, T_5, T_7)
REDUCE2(T_8, T_9, T_10, M0, M1, M2, M3, M4, T_2, T_3, M5, T_1)
VZERO T_2
VZERO T_3
VMSLG T_0, T_9, T_2, T_2
VMSLG T_0, T_10, T_3, T_3
// put r**2 to the right and r**4 to the left of R_0, R_1, R_2
VSLDB $8, T_8, T_8, T_8
VSLDB $8, T_9, T_9, T_9
VSLDB $8, T_10, T_10, T_10
VSLDB $8, T_2, T_2, T_2
VSLDB $8, T_3, T_3, T_3
VO T_8, R_0, R_0
VO T_9, R_1, R_1
VO T_10, R_2, R_2
VO T_2, R5_1, R5_1
VO T_3, R5_2, R5_2
CMPBLE R3, $80, load // less than or equal to 5 blocks in message
// 6(or 5+1) blocks
SUB $81, R3
VLM (R2), M0, M4
VLL R3, 80(R2), M5
ADD $1, R3
MOVBZ $1, R0
CMPBGE R3, $16, 2(PC)
VLVGB R3, R0, M5
MOVD $96(R2), R2
EXPACC(M0, M1, H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_0, T_1, T_2, T_3)
EXPACC(M2, M3, H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_0, T_1, T_2, T_3)
VLEIB $2, $1, H2_0
VLEIB $2, $1, H2_1
VLEIB $10, $1, H2_0
VLEIB $10, $1, H2_1
VZERO M0
VZERO M1
VZERO M2
VZERO M3
VZERO T_4
VZERO T_10
EXPACC(M4, M5, M0, M1, M2, M3, T_4, T_10, T_0, T_1, T_2, T_3)
VLR T_4, M4
VLEIB $10, $1, M2
CMPBLT R3, $16, 2(PC)
VLEIB $10, $1, T_10
MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, T_10, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M2, M3, M4, T_4, T_5, T_2, T_7, T_8, T_9)
VMRHG V0, H0_1, H0_0
VMRHG V0, H1_1, H1_0
VMRHG V0, H2_1, H2_0
VMRLG V0, H0_1, H0_1
VMRLG V0, H1_1, H1_1
VMRLG V0, H2_1, H2_1
SUB $16, R3
CMPBLE R3, $0, square
load:
// load EX0, EX1 and EX2
MOVD $·c<>(SB), R5
VLM (R5), EX0, EX2
loop:
CMPBLE R3, $64, add // b4 // last 4 or less blocks left
// next 4 full blocks
VLM (R2), M2, M5
SUB $64, R3
MOVD $64(R2), R2
REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, T_0, T_1, T_3, T_4, T_5, T_2, T_7, T_8, T_9)
// expacc in-lined to create [m2, m3] limbs
VGBM $0x3f3f, T_0 // 44 bit clear mask
VGBM $0x1f1f, T_1 // 40 bit clear mask
VPERM M2, M3, EX0, T_3
VESRLG $4, T_0, T_0 // 44 bit clear mask ready
VPERM M2, M3, EX1, T_4
VPERM M2, M3, EX2, T_5
VN T_0, T_3, T_3
VESRLG $4, T_4, T_4
VN T_1, T_5, T_5
VN T_0, T_4, T_4
VMRHG H0_1, T_3, H0_0
VMRHG H1_1, T_4, H1_0
VMRHG H2_1, T_5, H2_0
VMRLG H0_1, T_3, H0_1
VMRLG H1_1, T_4, H1_1
VMRLG H2_1, T_5, H2_1
VLEIB $10, $1, H2_0
VLEIB $10, $1, H2_1
VPERM M4, M5, EX0, T_3
VPERM M4, M5, EX1, T_4
VPERM M4, M5, EX2, T_5
VN T_0, T_3, T_3
VESRLG $4, T_4, T_4
VN T_1, T_5, T_5
VN T_0, T_4, T_4
VMRHG V0, T_3, M0
VMRHG V0, T_4, M1
VMRHG V0, T_5, M2
VMRLG V0, T_3, M3
VMRLG V0, T_4, M4
VMRLG V0, T_5, M5
VLEIB $10, $1, M2
VLEIB $10, $1, M5
MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
CMPBNE R3, $0, loop
REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M3, M4, M5, T_4, T_5, T_2, T_7, T_8, T_9)
VMRHG V0, H0_1, H0_0
VMRHG V0, H1_1, H1_0
VMRHG V0, H2_1, H2_0
VMRLG V0, H0_1, H0_1
VMRLG V0, H1_1, H1_1
VMRLG V0, H2_1, H2_1
// load EX0, EX1, EX2
MOVD $·constants<>(SB), R5
VLM (R5), EX0, EX2
// sum vectors
VAQ H0_0, H0_1, H0_0
VAQ H1_0, H1_1, H1_0
VAQ H2_0, H2_1, H2_0
// h may be >= 2*(2**130-5) so we need to reduce it again
// M0...M4 are used as temps here
REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, T_9, T_10, H0_1, M5)
next: // carry h1->h2
VLEIB $7, $0x28, T_1
VREPIB $4, T_2
VGBM $0x003F, T_3
VESRLG $4, T_3
// byte shift
VSRLB T_1, H1_0, T_4
// bit shift
VSRL T_2, T_4, T_4
// clear h1 carry bits
VN T_3, H1_0, H1_0
// add carry
VAQ T_4, H2_0, H2_0
// h is now < 2*(2**130-5)
// pack h into h1 (hi) and h0 (lo)
PACK(H0_0, H1_0, H2_0)
// if h > 2**130-5 then h -= 2**130-5
MOD(H0_0, H1_0, T_0, T_1, T_2)
// h += s
MOVD $·bswapMask<>(SB), R5
VL (R5), T_1
VL 16(R4), T_0
VPERM T_0, T_0, T_1, T_0 // reverse bytes (to big)
VAQ T_0, H0_0, H0_0
VPERM H0_0, H0_0, T_1, H0_0 // reverse bytes (to little)
VST H0_0, (R1)
RET
add:
// load EX0, EX1, EX2
MOVD $·constants<>(SB), R5
VLM (R5), EX0, EX2
REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M3, M4, M5, T_4, T_5, T_2, T_7, T_8, T_9)
VMRHG V0, H0_1, H0_0
VMRHG V0, H1_1, H1_0
VMRHG V0, H2_1, H2_0
VMRLG V0, H0_1, H0_1
VMRLG V0, H1_1, H1_1
VMRLG V0, H2_1, H2_1
CMPBLE R3, $64, b4
b4:
CMPBLE R3, $48, b3 // 3 blocks or less
// 4(3+1) blocks remaining
SUB $49, R3
VLM (R2), M0, M2
VLL R3, 48(R2), M3
ADD $1, R3
MOVBZ $1, R0
CMPBEQ R3, $16, 2(PC)
VLVGB R3, R0, M3
MOVD $64(R2), R2
EXPACC(M0, M1, H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_0, T_1, T_2, T_3)
VLEIB $10, $1, H2_0
VLEIB $10, $1, H2_1
VZERO M0
VZERO M1
VZERO M4
VZERO M5
VZERO T_4
VZERO T_10
EXPACC(M2, M3, M0, M1, M4, M5, T_4, T_10, T_0, T_1, T_2, T_3)
VLR T_4, M2
VLEIB $10, $1, M4
CMPBNE R3, $16, 2(PC)
VLEIB $10, $1, T_10
MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M4, M5, M2, T_10, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M3, M4, M5, T_4, T_5, T_2, T_7, T_8, T_9)
VMRHG V0, H0_1, H0_0
VMRHG V0, H1_1, H1_0
VMRHG V0, H2_1, H2_0
VMRLG V0, H0_1, H0_1
VMRLG V0, H1_1, H1_1
VMRLG V0, H2_1, H2_1
SUB $16, R3
CMPBLE R3, $0, square // this condition must always hold true!
b3:
CMPBLE R3, $32, b2
// 3 blocks remaining
// setup [r²,r]
VSLDB $8, R_0, R_0, R_0
VSLDB $8, R_1, R_1, R_1
VSLDB $8, R_2, R_2, R_2
VSLDB $8, R5_1, R5_1, R5_1
VSLDB $8, R5_2, R5_2, R5_2
VLVGG $1, RSAVE_0, R_0
VLVGG $1, RSAVE_1, R_1
VLVGG $1, RSAVE_2, R_2
VLVGG $1, R5SAVE_1, R5_1
VLVGG $1, R5SAVE_2, R5_2
// setup [h0, h1]
VSLDB $8, H0_0, H0_0, H0_0
VSLDB $8, H1_0, H1_0, H1_0
VSLDB $8, H2_0, H2_0, H2_0
VO H0_1, H0_0, H0_0
VO H1_1, H1_0, H1_0
VO H2_1, H2_0, H2_0
VZERO H0_1
VZERO H1_1
VZERO H2_1
VZERO M0
VZERO M1
VZERO M2
VZERO M3
VZERO M4
VZERO M5
// H*[r**2, r]
MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, H0_1, H1_1, T_10, M5)
SUB $33, R3
VLM (R2), M0, M1
VLL R3, 32(R2), M2
ADD $1, R3
MOVBZ $1, R0
CMPBEQ R3, $16, 2(PC)
VLVGB R3, R0, M2
// H += m0
VZERO T_1
VZERO T_2
VZERO T_3
EXPACC2(M0, T_1, T_2, T_3, T_4, T_5, T_6)
VLEIB $10, $1, T_3
VAG H0_0, T_1, H0_0
VAG H1_0, T_2, H1_0
VAG H2_0, T_3, H2_0
VZERO M0
VZERO M3
VZERO M4
VZERO M5
VZERO T_10
// (H+m0)*r
MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M3, M4, M5, V0, T_10, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
REDUCE2(H0_0, H1_0, H2_0, M0, M3, M4, M5, T_10, H0_1, H1_1, H2_1, T_9)
// H += m1
VZERO V0
VZERO T_1
VZERO T_2
VZERO T_3
EXPACC2(M1, T_1, T_2, T_3, T_4, T_5, T_6)
VLEIB $10, $1, T_3
VAQ H0_0, T_1, H0_0
VAQ H1_0, T_2, H1_0
VAQ H2_0, T_3, H2_0
REDUCE2(H0_0, H1_0, H2_0, M0, M3, M4, M5, T_9, H0_1, H1_1, H2_1, T_10)
// [H, m2] * [r**2, r]
EXPACC2(M2, H0_0, H1_0, H2_0, T_1, T_2, T_3)
CMPBNE R3, $16, 2(PC)
VLEIB $10, $1, H2_0
VZERO M0
VZERO M1
VZERO M2
VZERO M3
VZERO M4
VZERO M5
MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, H0_1, H1_1, M5, T_10)
SUB $16, R3
CMPBLE R3, $0, next // this condition must always hold true!
b2:
CMPBLE R3, $16, b1
// 2 blocks remaining
// setup [r²,r]
VSLDB $8, R_0, R_0, R_0
VSLDB $8, R_1, R_1, R_1
VSLDB $8, R_2, R_2, R_2
VSLDB $8, R5_1, R5_1, R5_1
VSLDB $8, R5_2, R5_2, R5_2
VLVGG $1, RSAVE_0, R_0
VLVGG $1, RSAVE_1, R_1
VLVGG $1, RSAVE_2, R_2
VLVGG $1, R5SAVE_1, R5_1
VLVGG $1, R5SAVE_2, R5_2
// setup [h0, h1]
VSLDB $8, H0_0, H0_0, H0_0
VSLDB $8, H1_0, H1_0, H1_0
VSLDB $8, H2_0, H2_0, H2_0
VO H0_1, H0_0, H0_0
VO H1_1, H1_0, H1_0
VO H2_1, H2_0, H2_0
VZERO H0_1
VZERO H1_1
VZERO H2_1
VZERO M0
VZERO M1
VZERO M2
VZERO M3
VZERO M4
VZERO M5
// H*[r**2, r]
MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M2, M3, M4, T_4, T_5, T_2, T_7, T_8, T_9)
VMRHG V0, H0_1, H0_0
VMRHG V0, H1_1, H1_0
VMRHG V0, H2_1, H2_0
VMRLG V0, H0_1, H0_1
VMRLG V0, H1_1, H1_1
VMRLG V0, H2_1, H2_1
// move h to the left and 0s at the right
VSLDB $8, H0_0, H0_0, H0_0
VSLDB $8, H1_0, H1_0, H1_0
VSLDB $8, H2_0, H2_0, H2_0
// get message blocks and append 1 to start
SUB $17, R3
VL (R2), M0
VLL R3, 16(R2), M1
ADD $1, R3
MOVBZ $1, R0
CMPBEQ R3, $16, 2(PC)
VLVGB R3, R0, M1
VZERO T_6
VZERO T_7
VZERO T_8
EXPACC2(M0, T_6, T_7, T_8, T_1, T_2, T_3)
EXPACC2(M1, T_6, T_7, T_8, T_1, T_2, T_3)
VLEIB $2, $1, T_8
CMPBNE R3, $16, 2(PC)
VLEIB $10, $1, T_8
// add [m0, m1] to h
VAG H0_0, T_6, H0_0
VAG H1_0, T_7, H1_0
VAG H2_0, T_8, H2_0
VZERO M2
VZERO M3
VZERO M4
VZERO M5
VZERO T_10
VZERO M0
// at this point R_0 .. R5_2 look like [r**2, r]
MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M2, M3, M4, M5, T_10, M0, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
REDUCE2(H0_0, H1_0, H2_0, M2, M3, M4, M5, T_9, H0_1, H1_1, H2_1, T_10)
SUB $16, R3, R3
CMPBLE R3, $0, next
b1:
CMPBLE R3, $0, next
// 1 block remaining
// setup [r²,r]
VSLDB $8, R_0, R_0, R_0
VSLDB $8, R_1, R_1, R_1
VSLDB $8, R_2, R_2, R_2
VSLDB $8, R5_1, R5_1, R5_1
VSLDB $8, R5_2, R5_2, R5_2
VLVGG $1, RSAVE_0, R_0
VLVGG $1, RSAVE_1, R_1
VLVGG $1, RSAVE_2, R_2
VLVGG $1, R5SAVE_1, R5_1
VLVGG $1, R5SAVE_2, R5_2
// setup [h0, h1]
VSLDB $8, H0_0, H0_0, H0_0
VSLDB $8, H1_0, H1_0, H1_0
VSLDB $8, H2_0, H2_0, H2_0
VO H0_1, H0_0, H0_0
VO H1_1, H1_0, H1_0
VO H2_1, H2_0, H2_0
VZERO H0_1
VZERO H1_1
VZERO H2_1
VZERO M0
VZERO M1
VZERO M2
VZERO M3
VZERO M4
VZERO M5
// H*[r**2, r]
MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, T_9, T_10, H0_1, M5)
// set up [0, m0] limbs
SUB $1, R3
VLL R3, (R2), M0
ADD $1, R3
MOVBZ $1, R0
CMPBEQ R3, $16, 2(PC)
VLVGB R3, R0, M0
VZERO T_1
VZERO T_2
VZERO T_3
EXPACC2(M0, T_1, T_2, T_3, T_4, T_5, T_6)// limbs: [0, m]
CMPBNE R3, $16, 2(PC)
VLEIB $10, $1, T_3
// h+m0
VAQ H0_0, T_1, H0_0
VAQ H1_0, T_2, H1_0
VAQ H2_0, T_3, H2_0
VZERO M0
VZERO M1
VZERO M2
VZERO M3
VZERO M4
VZERO M5
MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, T_9, T_10, H0_1, M5)
BR next
square:
// setup [r²,r]
VSLDB $8, R_0, R_0, R_0
VSLDB $8, R_1, R_1, R_1
VSLDB $8, R_2, R_2, R_2
VSLDB $8, R5_1, R5_1, R5_1
VSLDB $8, R5_2, R5_2, R5_2
VLVGG $1, RSAVE_0, R_0
VLVGG $1, RSAVE_1, R_1
VLVGG $1, RSAVE_2, R_2
VLVGG $1, R5SAVE_1, R5_1
VLVGG $1, R5SAVE_2, R5_2
// setup [h0, h1]
VSLDB $8, H0_0, H0_0, H0_0
VSLDB $8, H1_0, H1_0, H1_0
VSLDB $8, H2_0, H2_0, H2_0
VO H0_1, H0_0, H0_0
VO H1_1, H1_0, H1_0
VO H2_1, H2_0, H2_0
VZERO H0_1
VZERO H1_1
VZERO H2_1
VZERO M0
VZERO M1
VZERO M2
VZERO M3
VZERO M4
VZERO M5
// (h0*r**2) + (h1*r)
MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, T_9, T_10, H0_1, M5)
BR next

View File

@ -99,24 +99,30 @@ TEXT ·salsa2020XORKeyStream(SB),0,$456-40 // frame = 424 + 32 byte alignment
MOVL 36 (SP),CX MOVL 36 (SP),CX
MOVL DX,288(SP) MOVL DX,288(SP)
MOVL CX,304(SP) MOVL CX,304(SP)
ADDQ $1,DX
SHLQ $32,CX SHLQ $32,CX
ADDQ CX,DX ADDQ CX,DX
ADDQ $1,DX
MOVQ DX,CX MOVQ DX,CX
SHRQ $32,CX SHRQ $32,CX
MOVL DX, 292 (SP) MOVL DX, 292 (SP)
MOVL CX, 308 (SP) MOVL CX, 308 (SP)
ADDQ $1,DX ADDQ $1,DX
SHLQ $32,CX
ADDQ CX,DX
MOVQ DX,CX MOVQ DX,CX
SHRQ $32,CX SHRQ $32,CX
MOVL DX, 296 (SP) MOVL DX, 296 (SP)
MOVL CX, 312 (SP) MOVL CX, 312 (SP)
ADDQ $1,DX ADDQ $1,DX
SHLQ $32,CX
ADDQ CX,DX
MOVQ DX,CX MOVQ DX,CX
SHRQ $32,CX SHRQ $32,CX
MOVL DX, 300 (SP) MOVL DX, 300 (SP)
MOVL CX, 316 (SP) MOVL CX, 316 (SP)
ADDQ $1,DX ADDQ $1,DX
SHLQ $32,CX
ADDQ CX,DX
MOVQ DX,CX MOVQ DX,CX
SHRQ $32,CX SHRQ $32,CX
MOVL DX,16(SP) MOVL DX,16(SP)

View File

@ -6,9 +6,10 @@
package salsa package salsa
// This function is implemented in salsa2020_amd64.s.
//go:noescape //go:noescape
// salsa2020XORKeyStream is implemented in salsa20_amd64.s.
func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte) func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte)
// XORKeyStream crypts bytes from in to out using the given key and counters. // XORKeyStream crypts bytes from in to out using the given key and counters.

View File

@ -1,14 +0,0 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !amd64 appengine gccgo
package salsa
// XORKeyStream crypts bytes from in to out using the given key and counters.
// In and out must overlap entirely or not at all. Counter
// contains the raw salsa20 counter bytes (both nonce and block counter).
func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) {
genericXORKeyStream(out, in, counter, key)
}

View File

@ -2,6 +2,8 @@
// 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 !amd64 appengine gccgo
package salsa package salsa
const rounds = 20 const rounds = 20
@ -200,9 +202,10 @@ func core(out *[64]byte, in *[16]byte, k *[32]byte, c *[16]byte) {
out[63] = byte(x15 >> 24) out[63] = byte(x15 >> 24)
} }
// genericXORKeyStream is the generic implementation of XORKeyStream to be used // XORKeyStream crypts bytes from in to out using the given key and counters.
// when no assembly implementation is available. // In and out must overlap entirely or not at all. Counter
func genericXORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) { // contains the raw salsa20 counter bytes (both nonce and block counter).
func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) {
var block [64]byte var block [64]byte
var counterCopy [16]byte var counterCopy [16]byte
copy(counterCopy[:], counter[:]) copy(counterCopy[:], counter[:])

View File

@ -17,14 +17,12 @@ import (
// These constants from [PROTOCOL.certkeys] represent the algorithm names // These constants from [PROTOCOL.certkeys] represent the algorithm names
// for certificate types supported by this package. // for certificate types supported by this package.
const ( const (
CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com" CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com"
CertAlgoDSAv01 = "ssh-dss-cert-v01@openssh.com" CertAlgoDSAv01 = "ssh-dss-cert-v01@openssh.com"
CertAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com" CertAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com"
CertAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com" CertAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com"
CertAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com" CertAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com"
CertAlgoSKECDSA256v01 = "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com" CertAlgoED25519v01 = "ssh-ed25519-cert-v01@openssh.com"
CertAlgoED25519v01 = "ssh-ed25519-cert-v01@openssh.com"
CertAlgoSKED25519v01 = "sk-ssh-ed25519-cert-v01@openssh.com"
) )
// Certificate types distinguish between host and user // Certificate types distinguish between host and user
@ -39,7 +37,6 @@ const (
type Signature struct { type Signature struct {
Format string Format string
Blob []byte Blob []byte
Rest []byte `ssh:"rest"`
} }
// CertTimeInfinity can be used for OpenSSHCertV01.ValidBefore to indicate that // CertTimeInfinity can be used for OpenSSHCertV01.ValidBefore to indicate that
@ -414,8 +411,8 @@ func (c *CertChecker) CheckCert(principal string, cert *Certificate) error {
return nil return nil
} }
// SignCert signs the certificate with an authority, setting the Nonce, // SignCert sets c.SignatureKey to the authority's public key and stores a
// SignatureKey, and Signature fields. // Signature, by authority, in the certificate.
func (c *Certificate) SignCert(rand io.Reader, authority Signer) error { func (c *Certificate) SignCert(rand io.Reader, authority Signer) error {
c.Nonce = make([]byte, 32) c.Nonce = make([]byte, 32)
if _, err := io.ReadFull(rand, c.Nonce); err != nil { if _, err := io.ReadFull(rand, c.Nonce); err != nil {
@ -432,14 +429,12 @@ func (c *Certificate) SignCert(rand io.Reader, authority Signer) error {
} }
var certAlgoNames = map[string]string{ var certAlgoNames = map[string]string{
KeyAlgoRSA: CertAlgoRSAv01, KeyAlgoRSA: CertAlgoRSAv01,
KeyAlgoDSA: CertAlgoDSAv01, KeyAlgoDSA: CertAlgoDSAv01,
KeyAlgoECDSA256: CertAlgoECDSA256v01, KeyAlgoECDSA256: CertAlgoECDSA256v01,
KeyAlgoECDSA384: CertAlgoECDSA384v01, KeyAlgoECDSA384: CertAlgoECDSA384v01,
KeyAlgoECDSA521: CertAlgoECDSA521v01, KeyAlgoECDSA521: CertAlgoECDSA521v01,
KeyAlgoSKECDSA256: CertAlgoSKECDSA256v01, KeyAlgoED25519: CertAlgoED25519v01,
KeyAlgoED25519: CertAlgoED25519v01,
KeyAlgoSKED25519: CertAlgoSKED25519v01,
} }
// certToPrivAlgo returns the underlying algorithm for a certificate algorithm. // certToPrivAlgo returns the underlying algorithm for a certificate algorithm.
@ -523,12 +518,6 @@ func parseSignatureBody(in []byte) (out *Signature, rest []byte, ok bool) {
return return
} }
switch out.Format {
case KeyAlgoSKECDSA256, CertAlgoSKECDSA256v01, KeyAlgoSKED25519, CertAlgoSKED25519v01:
out.Rest = in
return out, nil, ok
}
return out, in, ok return out, in, ok
} }

View File

@ -16,8 +16,9 @@ import (
"hash" "hash"
"io" "io"
"io/ioutil" "io/ioutil"
"math/bits"
"golang.org/x/crypto/chacha20" "golang.org/x/crypto/internal/chacha20"
"golang.org/x/crypto/poly1305" "golang.org/x/crypto/poly1305"
) )
@ -119,7 +120,7 @@ var cipherModes = map[string]*cipherMode{
chacha20Poly1305ID: {64, 0, newChaCha20Cipher}, chacha20Poly1305ID: {64, 0, newChaCha20Cipher},
// CBC mode is insecure and so is not included in the default config. // CBC mode is insecure and so is not included in the default config.
// (See https://www.ieee-security.org/TC/SP2013/papers/4977a526.pdf). If absolutely // (See http://www.isg.rhul.ac.uk/~kp/SandPfinal.pdf). If absolutely
// needed, it's possible to specify a custom Config to enable it. // needed, it's possible to specify a custom Config to enable it.
// You should expect that an active attacker can recover plaintext if // You should expect that an active attacker can recover plaintext if
// you do. // you do.
@ -148,8 +149,8 @@ type streamPacketCipher struct {
macResult []byte macResult []byte
} }
// readCipherPacket reads and decrypt a single packet from the reader argument. // readPacket reads and decrypt a single packet from the reader argument.
func (s *streamPacketCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) { func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) {
if _, err := io.ReadFull(r, s.prefix[:]); err != nil { if _, err := io.ReadFull(r, s.prefix[:]); err != nil {
return nil, err return nil, err
} }
@ -220,8 +221,8 @@ func (s *streamPacketCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byt
return s.packetData[:length-paddingLength-1], nil return s.packetData[:length-paddingLength-1], nil
} }
// writeCipherPacket encrypts and sends a packet of data to the writer argument // writePacket encrypts and sends a packet of data to the writer argument
func (s *streamPacketCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { func (s *streamPacketCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error {
if len(packet) > maxPacket { if len(packet) > maxPacket {
return errors.New("ssh: packet too large") return errors.New("ssh: packet too large")
} }
@ -326,7 +327,7 @@ func newGCMCipher(key, iv, unusedMacKey []byte, unusedAlgs directionAlgorithms)
const gcmTagSize = 16 const gcmTagSize = 16
func (c *gcmCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { func (c *gcmCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error {
// Pad out to multiple of 16 bytes. This is different from the // Pad out to multiple of 16 bytes. This is different from the
// stream cipher because that encrypts the length too. // stream cipher because that encrypts the length too.
padding := byte(packetSizeMultiple - (1+len(packet))%packetSizeMultiple) padding := byte(packetSizeMultiple - (1+len(packet))%packetSizeMultiple)
@ -369,7 +370,7 @@ func (c *gcmCipher) incIV() {
} }
} }
func (c *gcmCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) { func (c *gcmCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) {
if _, err := io.ReadFull(r, c.prefix[:]); err != nil { if _, err := io.ReadFull(r, c.prefix[:]); err != nil {
return nil, err return nil, err
} }
@ -485,8 +486,8 @@ type cbcError string
func (e cbcError) Error() string { return string(e) } func (e cbcError) Error() string { return string(e) }
func (c *cbcCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) { func (c *cbcCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) {
p, err := c.readCipherPacketLeaky(seqNum, r) p, err := c.readPacketLeaky(seqNum, r)
if err != nil { if err != nil {
if _, ok := err.(cbcError); ok { if _, ok := err.(cbcError); ok {
// Verification error: read a fixed amount of // Verification error: read a fixed amount of
@ -499,7 +500,7 @@ func (c *cbcCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error)
return p, err return p, err
} }
func (c *cbcCipher) readCipherPacketLeaky(seqNum uint32, r io.Reader) ([]byte, error) { func (c *cbcCipher) readPacketLeaky(seqNum uint32, r io.Reader) ([]byte, error) {
blockSize := c.decrypter.BlockSize() blockSize := c.decrypter.BlockSize()
// Read the header, which will include some of the subsequent data in the // Read the header, which will include some of the subsequent data in the
@ -575,7 +576,7 @@ func (c *cbcCipher) readCipherPacketLeaky(seqNum uint32, r io.Reader) ([]byte, e
return c.packetData[prefixLen:paddingStart], nil return c.packetData[prefixLen:paddingStart], nil
} }
func (c *cbcCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { func (c *cbcCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error {
effectiveBlockSize := maxUInt32(cbcMinPacketSizeMultiple, c.encrypter.BlockSize()) effectiveBlockSize := maxUInt32(cbcMinPacketSizeMultiple, c.encrypter.BlockSize())
// Length of encrypted portion of the packet (header, payload, padding). // Length of encrypted portion of the packet (header, payload, padding).
@ -641,8 +642,8 @@ const chacha20Poly1305ID = "chacha20-poly1305@openssh.com"
// the methods here also implement padding, which RFC4253 Section 6 // the methods here also implement padding, which RFC4253 Section 6
// also requires of stream ciphers. // also requires of stream ciphers.
type chacha20Poly1305Cipher struct { type chacha20Poly1305Cipher struct {
lengthKey [32]byte lengthKey [8]uint32
contentKey [32]byte contentKey [8]uint32
buf []byte buf []byte
} }
@ -655,21 +656,21 @@ func newChaCha20Cipher(key, unusedIV, unusedMACKey []byte, unusedAlgs directionA
buf: make([]byte, 256), buf: make([]byte, 256),
} }
copy(c.contentKey[:], key[:32]) for i := range c.contentKey {
copy(c.lengthKey[:], key[32:]) c.contentKey[i] = binary.LittleEndian.Uint32(key[i*4 : (i+1)*4])
}
for i := range c.lengthKey {
c.lengthKey[i] = binary.LittleEndian.Uint32(key[(i+8)*4 : (i+9)*4])
}
return c, nil return c, nil
} }
func (c *chacha20Poly1305Cipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) { func (c *chacha20Poly1305Cipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) {
nonce := make([]byte, 12) nonce := [3]uint32{0, 0, bits.ReverseBytes32(seqNum)}
binary.BigEndian.PutUint32(nonce[8:], seqNum) s := chacha20.New(c.contentKey, nonce)
s, err := chacha20.NewUnauthenticatedCipher(c.contentKey[:], nonce) var polyKey [32]byte
if err != nil {
return nil, err
}
var polyKey, discardBuf [32]byte
s.XORKeyStream(polyKey[:], polyKey[:]) s.XORKeyStream(polyKey[:], polyKey[:])
s.XORKeyStream(discardBuf[:], discardBuf[:]) // skip the next 32 bytes s.Advance() // skip next 32 bytes
encryptedLength := c.buf[:4] encryptedLength := c.buf[:4]
if _, err := io.ReadFull(r, encryptedLength); err != nil { if _, err := io.ReadFull(r, encryptedLength); err != nil {
@ -677,11 +678,7 @@ func (c *chacha20Poly1305Cipher) readCipherPacket(seqNum uint32, r io.Reader) ([
} }
var lenBytes [4]byte var lenBytes [4]byte
ls, err := chacha20.NewUnauthenticatedCipher(c.lengthKey[:], nonce) chacha20.New(c.lengthKey, nonce).XORKeyStream(lenBytes[:], encryptedLength)
if err != nil {
return nil, err
}
ls.XORKeyStream(lenBytes[:], encryptedLength)
length := binary.BigEndian.Uint32(lenBytes[:]) length := binary.BigEndian.Uint32(lenBytes[:])
if length > maxPacket { if length > maxPacket {
@ -726,16 +723,12 @@ func (c *chacha20Poly1305Cipher) readCipherPacket(seqNum uint32, r io.Reader) ([
return plain, nil return plain, nil
} }
func (c *chacha20Poly1305Cipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, payload []byte) error { func (c *chacha20Poly1305Cipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, payload []byte) error {
nonce := make([]byte, 12) nonce := [3]uint32{0, 0, bits.ReverseBytes32(seqNum)}
binary.BigEndian.PutUint32(nonce[8:], seqNum) s := chacha20.New(c.contentKey, nonce)
s, err := chacha20.NewUnauthenticatedCipher(c.contentKey[:], nonce) var polyKey [32]byte
if err != nil {
return err
}
var polyKey, discardBuf [32]byte
s.XORKeyStream(polyKey[:], polyKey[:]) s.XORKeyStream(polyKey[:], polyKey[:])
s.XORKeyStream(discardBuf[:], discardBuf[:]) // skip the next 32 bytes s.Advance() // skip next 32 bytes
// There is no blocksize, so fall back to multiple of 8 byte // There is no blocksize, so fall back to multiple of 8 byte
// padding, as described in RFC 4253, Sec 6. // padding, as described in RFC 4253, Sec 6.
@ -755,11 +748,7 @@ func (c *chacha20Poly1305Cipher) writeCipherPacket(seqNum uint32, w io.Writer, r
} }
binary.BigEndian.PutUint32(c.buf, uint32(1+len(payload)+padding)) binary.BigEndian.PutUint32(c.buf, uint32(1+len(payload)+padding))
ls, err := chacha20.NewUnauthenticatedCipher(c.lengthKey[:], nonce) chacha20.New(c.lengthKey, nonce).XORKeyStream(c.buf, c.buf[:4])
if err != nil {
return err
}
ls.XORKeyStream(c.buf, c.buf[:4])
c.buf[4] = byte(padding) c.buf[4] = byte(padding)
copy(c.buf[5:], payload) copy(c.buf[5:], payload)
packetEnd := 5 + len(payload) + padding packetEnd := 5 + len(payload) + padding

View File

@ -36,7 +36,7 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error {
// during the authentication phase the client first attempts the "none" method // during the authentication phase the client first attempts the "none" method
// then any untried methods suggested by the server. // then any untried methods suggested by the server.
var tried []string tried := make(map[string]bool)
var lastMethods []string var lastMethods []string
sessionID := c.transport.getSessionID() sessionID := c.transport.getSessionID()
@ -49,9 +49,7 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error {
// success // success
return nil return nil
} else if ok == authFailure { } else if ok == authFailure {
if m := auth.method(); !contains(tried, m) { tried[auth.method()] = true
tried = append(tried, m)
}
} }
if methods == nil { if methods == nil {
methods = lastMethods methods = lastMethods
@ -63,7 +61,7 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error {
findNext: findNext:
for _, a := range config.Auth { for _, a := range config.Auth {
candidateMethod := a.method() candidateMethod := a.method()
if contains(tried, candidateMethod) { if tried[candidateMethod] {
continue continue
} }
for _, meth := range methods { for _, meth := range methods {
@ -74,16 +72,16 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error {
} }
} }
} }
return fmt.Errorf("ssh: unable to authenticate, attempted methods %v, no supported methods remain", tried) return fmt.Errorf("ssh: unable to authenticate, attempted methods %v, no supported methods remain", keys(tried))
} }
func contains(list []string, e string) bool { func keys(m map[string]bool) []string {
for _, s := range list { s := make([]string, 0, len(m))
if s == e {
return true for key := range m {
} s = append(s, key)
} }
return false return s
} }
// An AuthMethod represents an instance of an RFC 4252 authentication method. // An AuthMethod represents an instance of an RFC 4252 authentication method.
@ -525,117 +523,3 @@ func (r *retryableAuthMethod) method() string {
func RetryableAuthMethod(auth AuthMethod, maxTries int) AuthMethod { func RetryableAuthMethod(auth AuthMethod, maxTries int) AuthMethod {
return &retryableAuthMethod{authMethod: auth, maxTries: maxTries} return &retryableAuthMethod{authMethod: auth, maxTries: maxTries}
} }
// GSSAPIWithMICAuthMethod is an AuthMethod with "gssapi-with-mic" authentication.
// See RFC 4462 section 3
// gssAPIClient is implementation of the GSSAPIClient interface, see the definition of the interface for details.
// target is the server host you want to log in to.
func GSSAPIWithMICAuthMethod(gssAPIClient GSSAPIClient, target string) AuthMethod {
if gssAPIClient == nil {
panic("gss-api client must be not nil with enable gssapi-with-mic")
}
return &gssAPIWithMICCallback{gssAPIClient: gssAPIClient, target: target}
}
type gssAPIWithMICCallback struct {
gssAPIClient GSSAPIClient
target string
}
func (g *gssAPIWithMICCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) {
m := &userAuthRequestMsg{
User: user,
Service: serviceSSH,
Method: g.method(),
}
// The GSS-API authentication method is initiated when the client sends an SSH_MSG_USERAUTH_REQUEST.
// See RFC 4462 section 3.2.
m.Payload = appendU32(m.Payload, 1)
m.Payload = appendString(m.Payload, string(krb5OID))
if err := c.writePacket(Marshal(m)); err != nil {
return authFailure, nil, err
}
// The server responds to the SSH_MSG_USERAUTH_REQUEST with either an
// SSH_MSG_USERAUTH_FAILURE if none of the mechanisms are supported or
// with an SSH_MSG_USERAUTH_GSSAPI_RESPONSE.
// See RFC 4462 section 3.3.
// OpenSSH supports Kerberos V5 mechanism only for GSS-API authentication,so I don't want to check
// selected mech if it is valid.
packet, err := c.readPacket()
if err != nil {
return authFailure, nil, err
}
userAuthGSSAPIResp := &userAuthGSSAPIResponse{}
if err := Unmarshal(packet, userAuthGSSAPIResp); err != nil {
return authFailure, nil, err
}
// Start the loop into the exchange token.
// See RFC 4462 section 3.4.
var token []byte
defer g.gssAPIClient.DeleteSecContext()
for {
// Initiates the establishment of a security context between the application and a remote peer.
nextToken, needContinue, err := g.gssAPIClient.InitSecContext("host@"+g.target, token, false)
if err != nil {
return authFailure, nil, err
}
if len(nextToken) > 0 {
if err := c.writePacket(Marshal(&userAuthGSSAPIToken{
Token: nextToken,
})); err != nil {
return authFailure, nil, err
}
}
if !needContinue {
break
}
packet, err = c.readPacket()
if err != nil {
return authFailure, nil, err
}
switch packet[0] {
case msgUserAuthFailure:
var msg userAuthFailureMsg
if err := Unmarshal(packet, &msg); err != nil {
return authFailure, nil, err
}
if msg.PartialSuccess {
return authPartialSuccess, msg.Methods, nil
}
return authFailure, msg.Methods, nil
case msgUserAuthGSSAPIError:
userAuthGSSAPIErrorResp := &userAuthGSSAPIError{}
if err := Unmarshal(packet, userAuthGSSAPIErrorResp); err != nil {
return authFailure, nil, err
}
return authFailure, nil, fmt.Errorf("GSS-API Error:\n"+
"Major Status: %d\n"+
"Minor Status: %d\n"+
"Error Message: %s\n", userAuthGSSAPIErrorResp.MajorStatus, userAuthGSSAPIErrorResp.MinorStatus,
userAuthGSSAPIErrorResp.Message)
case msgUserAuthGSSAPIToken:
userAuthGSSAPITokenReq := &userAuthGSSAPIToken{}
if err := Unmarshal(packet, userAuthGSSAPITokenReq); err != nil {
return authFailure, nil, err
}
token = userAuthGSSAPITokenReq.Token
}
}
// Binding Encryption Keys.
// See RFC 4462 section 3.5.
micField := buildMIC(string(session), user, "ssh-connection", "gssapi-with-mic")
micToken, err := g.gssAPIClient.GetMIC(micField)
if err != nil {
return authFailure, nil, err
}
if err := c.writePacket(Marshal(&userAuthGSSAPIMIC{
MIC: micToken,
})); err != nil {
return authFailure, nil, err
}
return handleAuthResponse(c)
}
func (g *gssAPIWithMICCallback) method() string {
return "gssapi-with-mic"
}

View File

@ -51,21 +51,6 @@ var supportedKexAlgos = []string{
kexAlgoDH14SHA1, kexAlgoDH1SHA1, kexAlgoDH14SHA1, kexAlgoDH1SHA1,
} }
// serverForbiddenKexAlgos contains key exchange algorithms, that are forbidden
// for the server half.
var serverForbiddenKexAlgos = map[string]struct{}{
kexAlgoDHGEXSHA1: {}, // server half implementation is only minimal to satisfy the automated tests
kexAlgoDHGEXSHA256: {}, // server half implementation is only minimal to satisfy the automated tests
}
// preferredKexAlgos specifies the default preference for key-exchange algorithms
// in preference order.
var preferredKexAlgos = []string{
kexAlgoCurve25519SHA256,
kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521,
kexAlgoDH14SHA1,
}
// supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods // supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods
// of authenticating servers) in preference order. // of authenticating servers) in preference order.
var supportedHostKeyAlgos = []string{ var supportedHostKeyAlgos = []string{
@ -124,7 +109,6 @@ func findCommon(what string, client []string, server []string) (common string, e
return "", fmt.Errorf("ssh: no common algorithm for %s; client offered: %v, server offered: %v", what, client, server) return "", fmt.Errorf("ssh: no common algorithm for %s; client offered: %v, server offered: %v", what, client, server)
} }
// directionAlgorithms records algorithm choices in one direction (either read or write)
type directionAlgorithms struct { type directionAlgorithms struct {
Cipher string Cipher string
MAC string MAC string
@ -153,7 +137,7 @@ type algorithms struct {
r directionAlgorithms r directionAlgorithms
} }
func findAgreedAlgorithms(isClient bool, clientKexInit, serverKexInit *kexInitMsg) (algs *algorithms, err error) { func findAgreedAlgorithms(clientKexInit, serverKexInit *kexInitMsg) (algs *algorithms, err error) {
result := &algorithms{} result := &algorithms{}
result.kex, err = findCommon("key exchange", clientKexInit.KexAlgos, serverKexInit.KexAlgos) result.kex, err = findCommon("key exchange", clientKexInit.KexAlgos, serverKexInit.KexAlgos)
@ -166,37 +150,32 @@ func findAgreedAlgorithms(isClient bool, clientKexInit, serverKexInit *kexInitMs
return return
} }
stoc, ctos := &result.w, &result.r result.w.Cipher, err = findCommon("client to server cipher", clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer)
if isClient {
ctos, stoc = stoc, ctos
}
ctos.Cipher, err = findCommon("client to server cipher", clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer)
if err != nil { if err != nil {
return return
} }
stoc.Cipher, err = findCommon("server to client cipher", clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient) result.r.Cipher, err = findCommon("server to client cipher", clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient)
if err != nil { if err != nil {
return return
} }
ctos.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer) result.w.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer)
if err != nil { if err != nil {
return return
} }
stoc.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient) result.r.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient)
if err != nil { if err != nil {
return return
} }
ctos.Compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer) result.w.Compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer)
if err != nil { if err != nil {
return return
} }
stoc.Compression, err = findCommon("server to client compression", clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient) result.r.Compression, err = findCommon("server to client compression", clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient)
if err != nil { if err != nil {
return return
} }
@ -254,7 +233,7 @@ func (c *Config) SetDefaults() {
c.Ciphers = ciphers c.Ciphers = ciphers
if c.KeyExchanges == nil { if c.KeyExchanges == nil {
c.KeyExchanges = preferredKexAlgos c.KeyExchanges = supportedKexAlgos
} }
if c.MACs == nil { if c.MACs == nil {

View File

@ -543,8 +543,7 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
clientInit := otherInit clientInit := otherInit
serverInit := t.sentInitMsg serverInit := t.sentInitMsg
isClient := len(t.hostKeys) == 0 if len(t.hostKeys) == 0 {
if isClient {
clientInit, serverInit = serverInit, clientInit clientInit, serverInit = serverInit, clientInit
magics.clientKexInit = t.sentInitPacket magics.clientKexInit = t.sentInitPacket
@ -552,7 +551,7 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
} }
var err error var err error
t.algorithms, err = findAgreedAlgorithms(isClient, clientInit, serverInit) t.algorithms, err = findAgreedAlgorithms(clientInit, serverInit)
if err != nil { if err != nil {
return err return err
} }

View File

@ -1,93 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package bcrypt_pbkdf implements bcrypt_pbkdf(3) from OpenBSD.
//
// See https://flak.tedunangst.com/post/bcrypt-pbkdf and
// https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libutil/bcrypt_pbkdf.c.
package bcrypt_pbkdf
import (
"crypto/sha512"
"errors"
"golang.org/x/crypto/blowfish"
)
const blockSize = 32
// Key derives a key from the password, salt and rounds count, returning a
// []byte of length keyLen that can be used as cryptographic key.
func Key(password, salt []byte, rounds, keyLen int) ([]byte, error) {
if rounds < 1 {
return nil, errors.New("bcrypt_pbkdf: number of rounds is too small")
}
if len(password) == 0 {
return nil, errors.New("bcrypt_pbkdf: empty password")
}
if len(salt) == 0 || len(salt) > 1<<20 {
return nil, errors.New("bcrypt_pbkdf: bad salt length")
}
if keyLen > 1024 {
return nil, errors.New("bcrypt_pbkdf: keyLen is too large")
}
numBlocks := (keyLen + blockSize - 1) / blockSize
key := make([]byte, numBlocks*blockSize)
h := sha512.New()
h.Write(password)
shapass := h.Sum(nil)
shasalt := make([]byte, 0, sha512.Size)
cnt, tmp := make([]byte, 4), make([]byte, blockSize)
for block := 1; block <= numBlocks; block++ {
h.Reset()
h.Write(salt)
cnt[0] = byte(block >> 24)
cnt[1] = byte(block >> 16)
cnt[2] = byte(block >> 8)
cnt[3] = byte(block)
h.Write(cnt)
bcryptHash(tmp, shapass, h.Sum(shasalt))
out := make([]byte, blockSize)
copy(out, tmp)
for i := 2; i <= rounds; i++ {
h.Reset()
h.Write(tmp)
bcryptHash(tmp, shapass, h.Sum(shasalt))
for j := 0; j < len(out); j++ {
out[j] ^= tmp[j]
}
}
for i, v := range out {
key[i*numBlocks+(block-1)] = v
}
}
return key[:keyLen], nil
}
var magic = []byte("OxychromaticBlowfishSwatDynamite")
func bcryptHash(out, shapass, shasalt []byte) {
c, err := blowfish.NewSaltedCipher(shapass, shasalt)
if err != nil {
panic(err)
}
for i := 0; i < 64; i++ {
blowfish.ExpandKey(shasalt, c)
blowfish.ExpandKey(shapass, c)
}
copy(out, magic)
for i := 0; i < 32; i += 8 {
for j := 0; j < 64; j++ {
c.Encrypt(out[i:i+8], out[i:i+8])
}
}
// Swap bytes due to different endianness.
for i := 0; i < 32; i += 4 {
out[i+3], out[i+2], out[i+1], out[i] = out[i], out[i+1], out[i+2], out[i+3]
}
}

251
vendor/golang.org/x/crypto/ssh/kex.go generated vendored
View File

@ -10,9 +10,7 @@ import (
"crypto/elliptic" "crypto/elliptic"
"crypto/rand" "crypto/rand"
"crypto/subtle" "crypto/subtle"
"encoding/binary"
"errors" "errors"
"fmt"
"io" "io"
"math/big" "math/big"
@ -26,12 +24,6 @@ const (
kexAlgoECDH384 = "ecdh-sha2-nistp384" kexAlgoECDH384 = "ecdh-sha2-nistp384"
kexAlgoECDH521 = "ecdh-sha2-nistp521" kexAlgoECDH521 = "ecdh-sha2-nistp521"
kexAlgoCurve25519SHA256 = "curve25519-sha256@libssh.org" kexAlgoCurve25519SHA256 = "curve25519-sha256@libssh.org"
// For the following kex only the client half contains a production
// ready implementation. The server half only consists of a minimal
// implementation to satisfy the automated tests.
kexAlgoDHGEXSHA1 = "diffie-hellman-group-exchange-sha1"
kexAlgoDHGEXSHA256 = "diffie-hellman-group-exchange-sha256"
) )
// kexResult captures the outcome of a key exchange. // kexResult captures the outcome of a key exchange.
@ -212,7 +204,7 @@ func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handsha
HostKey: hostKeyBytes, HostKey: hostKeyBytes,
Signature: sig, Signature: sig,
Hash: crypto.SHA1, Hash: crypto.SHA1,
}, err }, nil
} }
// ecdh performs Elliptic Curve Diffie-Hellman key exchange as // ecdh performs Elliptic Curve Diffie-Hellman key exchange as
@ -410,8 +402,6 @@ func init() {
kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()} kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()}
kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()} kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()}
kexAlgoMap[kexAlgoCurve25519SHA256] = &curve25519sha256{} kexAlgoMap[kexAlgoCurve25519SHA256] = &curve25519sha256{}
kexAlgoMap[kexAlgoDHGEXSHA1] = &dhGEXSHA{hashFunc: crypto.SHA1}
kexAlgoMap[kexAlgoDHGEXSHA256] = &dhGEXSHA{hashFunc: crypto.SHA256}
} }
// curve25519sha256 implements the curve25519-sha256@libssh.org key // curve25519sha256 implements the curve25519-sha256@libssh.org key
@ -548,242 +538,3 @@ func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handsh
Hash: crypto.SHA256, Hash: crypto.SHA256,
}, nil }, nil
} }
// dhGEXSHA implements the diffie-hellman-group-exchange-sha1 and
// diffie-hellman-group-exchange-sha256 key agreement protocols,
// as described in RFC 4419
type dhGEXSHA struct {
g, p *big.Int
hashFunc crypto.Hash
}
const numMRTests = 64
const (
dhGroupExchangeMinimumBits = 2048
dhGroupExchangePreferredBits = 2048
dhGroupExchangeMaximumBits = 8192
)
func (gex *dhGEXSHA) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) {
if theirPublic.Sign() <= 0 || theirPublic.Cmp(gex.p) >= 0 {
return nil, fmt.Errorf("ssh: DH parameter out of bounds")
}
return new(big.Int).Exp(theirPublic, myPrivate, gex.p), nil
}
func (gex dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) {
// Send GexRequest
kexDHGexRequest := kexDHGexRequestMsg{
MinBits: dhGroupExchangeMinimumBits,
PreferedBits: dhGroupExchangePreferredBits,
MaxBits: dhGroupExchangeMaximumBits,
}
if err := c.writePacket(Marshal(&kexDHGexRequest)); err != nil {
return nil, err
}
// Receive GexGroup
packet, err := c.readPacket()
if err != nil {
return nil, err
}
var kexDHGexGroup kexDHGexGroupMsg
if err = Unmarshal(packet, &kexDHGexGroup); err != nil {
return nil, err
}
// reject if p's bit length < dhGroupExchangeMinimumBits or > dhGroupExchangeMaximumBits
if kexDHGexGroup.P.BitLen() < dhGroupExchangeMinimumBits || kexDHGexGroup.P.BitLen() > dhGroupExchangeMaximumBits {
return nil, fmt.Errorf("ssh: server-generated gex p is out of range (%d bits)", kexDHGexGroup.P.BitLen())
}
gex.p = kexDHGexGroup.P
gex.g = kexDHGexGroup.G
// Check if p is safe by verifing that p and (p-1)/2 are primes
one := big.NewInt(1)
var pHalf = &big.Int{}
pHalf.Rsh(gex.p, 1)
if !gex.p.ProbablyPrime(numMRTests) || !pHalf.ProbablyPrime(numMRTests) {
return nil, fmt.Errorf("ssh: server provided gex p is not safe")
}
// Check if g is safe by verifing that g > 1 and g < p - 1
var pMinusOne = &big.Int{}
pMinusOne.Sub(gex.p, one)
if gex.g.Cmp(one) != 1 && gex.g.Cmp(pMinusOne) != -1 {
return nil, fmt.Errorf("ssh: server provided gex g is not safe")
}
// Send GexInit
x, err := rand.Int(randSource, pHalf)
if err != nil {
return nil, err
}
X := new(big.Int).Exp(gex.g, x, gex.p)
kexDHGexInit := kexDHGexInitMsg{
X: X,
}
if err := c.writePacket(Marshal(&kexDHGexInit)); err != nil {
return nil, err
}
// Receive GexReply
packet, err = c.readPacket()
if err != nil {
return nil, err
}
var kexDHGexReply kexDHGexReplyMsg
if err = Unmarshal(packet, &kexDHGexReply); err != nil {
return nil, err
}
kInt, err := gex.diffieHellman(kexDHGexReply.Y, x)
if err != nil {
return nil, err
}
// Check if k is safe by verifing that k > 1 and k < p - 1
if kInt.Cmp(one) != 1 && kInt.Cmp(pMinusOne) != -1 {
return nil, fmt.Errorf("ssh: derived k is not safe")
}
h := gex.hashFunc.New()
magics.write(h)
writeString(h, kexDHGexReply.HostKey)
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits))
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits))
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits))
writeInt(h, gex.p)
writeInt(h, gex.g)
writeInt(h, X)
writeInt(h, kexDHGexReply.Y)
K := make([]byte, intLength(kInt))
marshalInt(K, kInt)
h.Write(K)
return &kexResult{
H: h.Sum(nil),
K: K,
HostKey: kexDHGexReply.HostKey,
Signature: kexDHGexReply.Signature,
Hash: gex.hashFunc,
}, nil
}
// Server half implementation of the Diffie Hellman Key Exchange with SHA1 and SHA256.
//
// This is a minimal implementation to satisfy the automated tests.
func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
// Receive GexRequest
packet, err := c.readPacket()
if err != nil {
return
}
var kexDHGexRequest kexDHGexRequestMsg
if err = Unmarshal(packet, &kexDHGexRequest); err != nil {
return
}
// smoosh the user's preferred size into our own limits
if kexDHGexRequest.PreferedBits > dhGroupExchangeMaximumBits {
kexDHGexRequest.PreferedBits = dhGroupExchangeMaximumBits
}
if kexDHGexRequest.PreferedBits < dhGroupExchangeMinimumBits {
kexDHGexRequest.PreferedBits = dhGroupExchangeMinimumBits
}
// fix min/max if they're inconsistent. technically, we could just pout
// and hang up, but there's no harm in giving them the benefit of the
// doubt and just picking a bitsize for them.
if kexDHGexRequest.MinBits > kexDHGexRequest.PreferedBits {
kexDHGexRequest.MinBits = kexDHGexRequest.PreferedBits
}
if kexDHGexRequest.MaxBits < kexDHGexRequest.PreferedBits {
kexDHGexRequest.MaxBits = kexDHGexRequest.PreferedBits
}
// Send GexGroup
// This is the group called diffie-hellman-group14-sha1 in RFC
// 4253 and Oakley Group 14 in RFC 3526.
p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
gex.p = p
gex.g = big.NewInt(2)
kexDHGexGroup := kexDHGexGroupMsg{
P: gex.p,
G: gex.g,
}
if err := c.writePacket(Marshal(&kexDHGexGroup)); err != nil {
return nil, err
}
// Receive GexInit
packet, err = c.readPacket()
if err != nil {
return
}
var kexDHGexInit kexDHGexInitMsg
if err = Unmarshal(packet, &kexDHGexInit); err != nil {
return
}
var pHalf = &big.Int{}
pHalf.Rsh(gex.p, 1)
y, err := rand.Int(randSource, pHalf)
if err != nil {
return
}
Y := new(big.Int).Exp(gex.g, y, gex.p)
kInt, err := gex.diffieHellman(kexDHGexInit.X, y)
if err != nil {
return nil, err
}
hostKeyBytes := priv.PublicKey().Marshal()
h := gex.hashFunc.New()
magics.write(h)
writeString(h, hostKeyBytes)
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits))
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits))
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits))
writeInt(h, gex.p)
writeInt(h, gex.g)
writeInt(h, kexDHGexInit.X)
writeInt(h, Y)
K := make([]byte, intLength(kInt))
marshalInt(K, kInt)
h.Write(K)
H := h.Sum(nil)
// H is already a hash, but the hostkey signing will apply its
// own key-specific hash algorithm.
sig, err := signAndMarshal(priv, randSource, H)
if err != nil {
return nil, err
}
kexDHGexReply := kexDHGexReplyMsg{
HostKey: hostKeyBytes,
Y: Y,
Signature: sig,
}
packet = Marshal(&kexDHGexReply)
err = c.writePacket(packet)
return &kexResult{
H: H,
K: K,
HostKey: hostKeyBytes,
Signature: sig,
Hash: gex.hashFunc,
}, err
}

View File

@ -7,8 +7,6 @@ package ssh
import ( import (
"bytes" "bytes"
"crypto" "crypto"
"crypto/aes"
"crypto/cipher"
"crypto/dsa" "crypto/dsa"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/elliptic" "crypto/elliptic"
@ -27,20 +25,17 @@ import (
"strings" "strings"
"golang.org/x/crypto/ed25519" "golang.org/x/crypto/ed25519"
"golang.org/x/crypto/ssh/internal/bcrypt_pbkdf"
) )
// These constants represent the algorithm names for key types supported by this // These constants represent the algorithm names for key types supported by this
// package. // package.
const ( const (
KeyAlgoRSA = "ssh-rsa" KeyAlgoRSA = "ssh-rsa"
KeyAlgoDSA = "ssh-dss" KeyAlgoDSA = "ssh-dss"
KeyAlgoECDSA256 = "ecdsa-sha2-nistp256" KeyAlgoECDSA256 = "ecdsa-sha2-nistp256"
KeyAlgoSKECDSA256 = "sk-ecdsa-sha2-nistp256@openssh.com" KeyAlgoECDSA384 = "ecdsa-sha2-nistp384"
KeyAlgoECDSA384 = "ecdsa-sha2-nistp384" KeyAlgoECDSA521 = "ecdsa-sha2-nistp521"
KeyAlgoECDSA521 = "ecdsa-sha2-nistp521" KeyAlgoED25519 = "ssh-ed25519"
KeyAlgoED25519 = "ssh-ed25519"
KeyAlgoSKED25519 = "sk-ssh-ed25519@openssh.com"
) )
// These constants represent non-default signature algorithms that are supported // These constants represent non-default signature algorithms that are supported
@ -63,13 +58,9 @@ func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err err
return parseDSA(in) return parseDSA(in)
case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521: case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521:
return parseECDSA(in) return parseECDSA(in)
case KeyAlgoSKECDSA256:
return parseSKECDSA(in)
case KeyAlgoED25519: case KeyAlgoED25519:
return parseED25519(in) return parseED25519(in)
case KeyAlgoSKED25519: case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01:
return parseSKEd25519(in)
case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoSKECDSA256v01, CertAlgoED25519v01, CertAlgoSKED25519v01:
cert, err := parseCert(in, certToPrivAlgo(algo)) cert, err := parseCert(in, certToPrivAlgo(algo))
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@ -562,11 +553,9 @@ func parseED25519(in []byte) (out PublicKey, rest []byte, err error) {
return nil, nil, err return nil, nil, err
} }
if l := len(w.KeyBytes); l != ed25519.PublicKeySize { key := ed25519.PublicKey(w.KeyBytes)
return nil, nil, fmt.Errorf("invalid size %d for Ed25519 public key", l)
}
return ed25519PublicKey(w.KeyBytes), w.Rest, nil return (ed25519PublicKey)(key), w.Rest, nil
} }
func (k ed25519PublicKey) Marshal() []byte { func (k ed25519PublicKey) Marshal() []byte {
@ -584,11 +573,9 @@ func (k ed25519PublicKey) Verify(b []byte, sig *Signature) error {
if sig.Format != k.Type() { if sig.Format != k.Type() {
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
} }
if l := len(k); l != ed25519.PublicKeySize {
return fmt.Errorf("ssh: invalid size %d for Ed25519 public key", l)
}
if ok := ed25519.Verify(ed25519.PublicKey(k), b, sig.Blob); !ok { edKey := (ed25519.PublicKey)(k)
if ok := ed25519.Verify(edKey, b, sig.Blob); !ok {
return errors.New("ssh: signature did not verify") return errors.New("ssh: signature did not verify")
} }
@ -698,224 +685,6 @@ func (k *ecdsaPublicKey) CryptoPublicKey() crypto.PublicKey {
return (*ecdsa.PublicKey)(k) return (*ecdsa.PublicKey)(k)
} }
// skFields holds the additional fields present in U2F/FIDO2 signatures.
// See openssh/PROTOCOL.u2f 'SSH U2F Signatures' for details.
type skFields struct {
// Flags contains U2F/FIDO2 flags such as 'user present'
Flags byte
// Counter is a monotonic signature counter which can be
// used to detect concurrent use of a private key, should
// it be extracted from hardware.
Counter uint32
}
type skECDSAPublicKey struct {
// application is a URL-like string, typically "ssh:" for SSH.
// see openssh/PROTOCOL.u2f for details.
application string
ecdsa.PublicKey
}
func (k *skECDSAPublicKey) Type() string {
return KeyAlgoSKECDSA256
}
func (k *skECDSAPublicKey) nistID() string {
return "nistp256"
}
func parseSKECDSA(in []byte) (out PublicKey, rest []byte, err error) {
var w struct {
Curve string
KeyBytes []byte
Application string
Rest []byte `ssh:"rest"`
}
if err := Unmarshal(in, &w); err != nil {
return nil, nil, err
}
key := new(skECDSAPublicKey)
key.application = w.Application
if w.Curve != "nistp256" {
return nil, nil, errors.New("ssh: unsupported curve")
}
key.Curve = elliptic.P256()
key.X, key.Y = elliptic.Unmarshal(key.Curve, w.KeyBytes)
if key.X == nil || key.Y == nil {
return nil, nil, errors.New("ssh: invalid curve point")
}
return key, w.Rest, nil
}
func (k *skECDSAPublicKey) Marshal() []byte {
// See RFC 5656, section 3.1.
keyBytes := elliptic.Marshal(k.Curve, k.X, k.Y)
w := struct {
Name string
ID string
Key []byte
Application string
}{
k.Type(),
k.nistID(),
keyBytes,
k.application,
}
return Marshal(&w)
}
func (k *skECDSAPublicKey) Verify(data []byte, sig *Signature) error {
if sig.Format != k.Type() {
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
}
h := ecHash(k.Curve).New()
h.Write([]byte(k.application))
appDigest := h.Sum(nil)
h.Reset()
h.Write(data)
dataDigest := h.Sum(nil)
var ecSig struct {
R *big.Int
S *big.Int
}
if err := Unmarshal(sig.Blob, &ecSig); err != nil {
return err
}
var skf skFields
if err := Unmarshal(sig.Rest, &skf); err != nil {
return err
}
blob := struct {
ApplicationDigest []byte `ssh:"rest"`
Flags byte
Counter uint32
MessageDigest []byte `ssh:"rest"`
}{
appDigest,
skf.Flags,
skf.Counter,
dataDigest,
}
original := Marshal(blob)
h.Reset()
h.Write(original)
digest := h.Sum(nil)
if ecdsa.Verify((*ecdsa.PublicKey)(&k.PublicKey), digest, ecSig.R, ecSig.S) {
return nil
}
return errors.New("ssh: signature did not verify")
}
type skEd25519PublicKey struct {
// application is a URL-like string, typically "ssh:" for SSH.
// see openssh/PROTOCOL.u2f for details.
application string
ed25519.PublicKey
}
func (k *skEd25519PublicKey) Type() string {
return KeyAlgoSKED25519
}
func parseSKEd25519(in []byte) (out PublicKey, rest []byte, err error) {
var w struct {
KeyBytes []byte
Application string
Rest []byte `ssh:"rest"`
}
if err := Unmarshal(in, &w); err != nil {
return nil, nil, err
}
if l := len(w.KeyBytes); l != ed25519.PublicKeySize {
return nil, nil, fmt.Errorf("invalid size %d for Ed25519 public key", l)
}
key := new(skEd25519PublicKey)
key.application = w.Application
key.PublicKey = ed25519.PublicKey(w.KeyBytes)
return key, w.Rest, nil
}
func (k *skEd25519PublicKey) Marshal() []byte {
w := struct {
Name string
KeyBytes []byte
Application string
}{
KeyAlgoSKED25519,
[]byte(k.PublicKey),
k.application,
}
return Marshal(&w)
}
func (k *skEd25519PublicKey) Verify(data []byte, sig *Signature) error {
if sig.Format != k.Type() {
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
}
if l := len(k.PublicKey); l != ed25519.PublicKeySize {
return fmt.Errorf("invalid size %d for Ed25519 public key", l)
}
h := sha256.New()
h.Write([]byte(k.application))
appDigest := h.Sum(nil)
h.Reset()
h.Write(data)
dataDigest := h.Sum(nil)
var edSig struct {
Signature []byte `ssh:"rest"`
}
if err := Unmarshal(sig.Blob, &edSig); err != nil {
return err
}
var skf skFields
if err := Unmarshal(sig.Rest, &skf); err != nil {
return err
}
blob := struct {
ApplicationDigest []byte `ssh:"rest"`
Flags byte
Counter uint32
MessageDigest []byte `ssh:"rest"`
}{
appDigest,
skf.Flags,
skf.Counter,
dataDigest,
}
original := Marshal(blob)
if ok := ed25519.Verify(k.PublicKey, original, edSig.Signature); !ok {
return errors.New("ssh: signature did not verify")
}
return nil
}
// NewSignerFromKey takes an *rsa.PrivateKey, *dsa.PrivateKey, // NewSignerFromKey takes an *rsa.PrivateKey, *dsa.PrivateKey,
// *ecdsa.PrivateKey or any other crypto.Signer and returns a // *ecdsa.PrivateKey or any other crypto.Signer and returns a
// corresponding Signer instance. ECDSA keys must use P-256, P-384 or // corresponding Signer instance. ECDSA keys must use P-256, P-384 or
@ -1061,18 +830,14 @@ func NewPublicKey(key interface{}) (PublicKey, error) {
case *dsa.PublicKey: case *dsa.PublicKey:
return (*dsaPublicKey)(key), nil return (*dsaPublicKey)(key), nil
case ed25519.PublicKey: case ed25519.PublicKey:
if l := len(key); l != ed25519.PublicKeySize { return (ed25519PublicKey)(key), nil
return nil, fmt.Errorf("ssh: invalid size %d for Ed25519 public key", l)
}
return ed25519PublicKey(key), nil
default: default:
return nil, fmt.Errorf("ssh: unsupported key type %T", key) return nil, fmt.Errorf("ssh: unsupported key type %T", key)
} }
} }
// ParsePrivateKey returns a Signer from a PEM encoded private key. It supports // ParsePrivateKey returns a Signer from a PEM encoded private key. It supports
// the same keys as ParseRawPrivateKey. If the private key is encrypted, it // the same keys as ParseRawPrivateKey.
// will return a PassphraseMissingError.
func ParsePrivateKey(pemBytes []byte) (Signer, error) { func ParsePrivateKey(pemBytes []byte) (Signer, error) {
key, err := ParseRawPrivateKey(pemBytes) key, err := ParseRawPrivateKey(pemBytes)
if err != nil { if err != nil {
@ -1085,8 +850,8 @@ func ParsePrivateKey(pemBytes []byte) (Signer, error) {
// ParsePrivateKeyWithPassphrase returns a Signer from a PEM encoded private // ParsePrivateKeyWithPassphrase returns a Signer from a PEM encoded private
// key and passphrase. It supports the same keys as // key and passphrase. It supports the same keys as
// ParseRawPrivateKeyWithPassphrase. // ParseRawPrivateKeyWithPassphrase.
func ParsePrivateKeyWithPassphrase(pemBytes, passphrase []byte) (Signer, error) { func ParsePrivateKeyWithPassphrase(pemBytes, passPhrase []byte) (Signer, error) {
key, err := ParseRawPrivateKeyWithPassphrase(pemBytes, passphrase) key, err := ParseRawPrivateKeyWithPassphrase(pemBytes, passPhrase)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -1102,21 +867,8 @@ func encryptedBlock(block *pem.Block) bool {
return strings.Contains(block.Headers["Proc-Type"], "ENCRYPTED") return strings.Contains(block.Headers["Proc-Type"], "ENCRYPTED")
} }
// A PassphraseMissingError indicates that parsing this private key requires a
// passphrase. Use ParsePrivateKeyWithPassphrase.
type PassphraseMissingError struct {
// PublicKey will be set if the private key format includes an unencrypted
// public key along with the encrypted private key.
PublicKey PublicKey
}
func (*PassphraseMissingError) Error() string {
return "ssh: this private key is passphrase protected"
}
// ParseRawPrivateKey returns a private key from a PEM encoded private key. It // ParseRawPrivateKey returns a private key from a PEM encoded private key. It
// supports RSA (PKCS#1), PKCS#8, DSA (OpenSSL), and ECDSA private keys. If the // supports RSA (PKCS#1), PKCS#8, DSA (OpenSSL), and ECDSA private keys.
// private key is encrypted, it will return a PassphraseMissingError.
func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) { func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) {
block, _ := pem.Decode(pemBytes) block, _ := pem.Decode(pemBytes)
if block == nil { if block == nil {
@ -1124,7 +876,7 @@ func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) {
} }
if encryptedBlock(block) { if encryptedBlock(block) {
return nil, &PassphraseMissingError{} return nil, errors.New("ssh: cannot decode encrypted private keys")
} }
switch block.Type { switch block.Type {
@ -1138,35 +890,33 @@ func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) {
case "DSA PRIVATE KEY": case "DSA PRIVATE KEY":
return ParseDSAPrivateKey(block.Bytes) return ParseDSAPrivateKey(block.Bytes)
case "OPENSSH PRIVATE KEY": case "OPENSSH PRIVATE KEY":
return parseOpenSSHPrivateKey(block.Bytes, unencryptedOpenSSHKey) return parseOpenSSHPrivateKey(block.Bytes)
default: default:
return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type) return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type)
} }
} }
// ParseRawPrivateKeyWithPassphrase returns a private key decrypted with // ParseRawPrivateKeyWithPassphrase returns a private key decrypted with
// passphrase from a PEM encoded private key. If the passphrase is wrong, it // passphrase from a PEM encoded private key. If wrong passphrase, return
// will return x509.IncorrectPasswordError. // x509.IncorrectPasswordError.
func ParseRawPrivateKeyWithPassphrase(pemBytes, passphrase []byte) (interface{}, error) { func ParseRawPrivateKeyWithPassphrase(pemBytes, passPhrase []byte) (interface{}, error) {
block, _ := pem.Decode(pemBytes) block, _ := pem.Decode(pemBytes)
if block == nil { if block == nil {
return nil, errors.New("ssh: no key found") return nil, errors.New("ssh: no key found")
} }
buf := block.Bytes
if block.Type == "OPENSSH PRIVATE KEY" { if encryptedBlock(block) {
return parseOpenSSHPrivateKey(block.Bytes, passphraseProtectedOpenSSHKey(passphrase)) if x509.IsEncryptedPEMBlock(block) {
} var err error
buf, err = x509.DecryptPEMBlock(block, passPhrase)
if !encryptedBlock(block) || !x509.IsEncryptedPEMBlock(block) { if err != nil {
return nil, errors.New("ssh: not an encrypted key") if err == x509.IncorrectPasswordError {
} return nil, err
}
buf, err := x509.DecryptPEMBlock(block, passphrase) return nil, fmt.Errorf("ssh: cannot decode encrypted private keys: %v", err)
if err != nil { }
if err == x509.IncorrectPasswordError {
return nil, err
} }
return nil, fmt.Errorf("ssh: cannot decode encrypted private keys: %v", err)
} }
switch block.Type { switch block.Type {
@ -1176,6 +926,8 @@ func ParseRawPrivateKeyWithPassphrase(pemBytes, passphrase []byte) (interface{},
return x509.ParseECPrivateKey(buf) return x509.ParseECPrivateKey(buf)
case "DSA PRIVATE KEY": case "DSA PRIVATE KEY":
return ParseDSAPrivateKey(buf) return ParseDSAPrivateKey(buf)
case "OPENSSH PRIVATE KEY":
return parseOpenSSHPrivateKey(buf)
default: default:
return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type) return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type)
} }
@ -1213,68 +965,9 @@ func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
}, nil }, nil
} }
func unencryptedOpenSSHKey(cipherName, kdfName, kdfOpts string, privKeyBlock []byte) ([]byte, error) { // Implemented based on the documentation at
if kdfName != "none" || cipherName != "none" { // https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key
return nil, &PassphraseMissingError{} func parseOpenSSHPrivateKey(key []byte) (crypto.PrivateKey, error) {
}
if kdfOpts != "" {
return nil, errors.New("ssh: invalid openssh private key")
}
return privKeyBlock, nil
}
func passphraseProtectedOpenSSHKey(passphrase []byte) openSSHDecryptFunc {
return func(cipherName, kdfName, kdfOpts string, privKeyBlock []byte) ([]byte, error) {
if kdfName == "none" || cipherName == "none" {
return nil, errors.New("ssh: key is not password protected")
}
if kdfName != "bcrypt" {
return nil, fmt.Errorf("ssh: unknown KDF %q, only supports %q", kdfName, "bcrypt")
}
var opts struct {
Salt string
Rounds uint32
}
if err := Unmarshal([]byte(kdfOpts), &opts); err != nil {
return nil, err
}
k, err := bcrypt_pbkdf.Key(passphrase, []byte(opts.Salt), int(opts.Rounds), 32+16)
if err != nil {
return nil, err
}
key, iv := k[:32], k[32:]
c, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
switch cipherName {
case "aes256-ctr":
ctr := cipher.NewCTR(c, iv)
ctr.XORKeyStream(privKeyBlock, privKeyBlock)
case "aes256-cbc":
if len(privKeyBlock)%c.BlockSize() != 0 {
return nil, fmt.Errorf("ssh: invalid encrypted private key length, not a multiple of the block size")
}
cbc := cipher.NewCBCDecrypter(c, iv)
cbc.CryptBlocks(privKeyBlock, privKeyBlock)
default:
return nil, fmt.Errorf("ssh: unknown cipher %q, only supports %q or %q", cipherName, "aes256-ctr", "aes256-cbc")
}
return privKeyBlock, nil
}
}
type openSSHDecryptFunc func(CipherName, KdfName, KdfOpts string, PrivKeyBlock []byte) ([]byte, error)
// parseOpenSSHPrivateKey parses an OpenSSH private key, using the decrypt
// function to unwrap the encrypted portion. unencryptedOpenSSHKey can be used
// as the decrypt function to parse an unencrypted private key. See
// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key.
func parseOpenSSHPrivateKey(key []byte, decrypt openSSHDecryptFunc) (crypto.PrivateKey, error) {
const magic = "openssh-key-v1\x00" const magic = "openssh-key-v1\x00"
if len(key) < len(magic) || string(key[:len(magic)]) != magic { if len(key) < len(magic) || string(key[:len(magic)]) != magic {
return nil, errors.New("ssh: invalid openssh private key format") return nil, errors.New("ssh: invalid openssh private key format")
@ -1293,22 +986,9 @@ func parseOpenSSHPrivateKey(key []byte, decrypt openSSHDecryptFunc) (crypto.Priv
if err := Unmarshal(remaining, &w); err != nil { if err := Unmarshal(remaining, &w); err != nil {
return nil, err return nil, err
} }
if w.NumKeys != 1 {
// We only support single key files, and so does OpenSSH.
// https://github.com/openssh/openssh-portable/blob/4103a3ec7/sshkey.c#L4171
return nil, errors.New("ssh: multi-key files are not supported")
}
privKeyBlock, err := decrypt(w.CipherName, w.KdfName, w.KdfOpts, w.PrivKeyBlock) if w.KdfName != "none" || w.CipherName != "none" {
if err != nil { return nil, errors.New("ssh: cannot decode encrypted private keys")
if err, ok := err.(*PassphraseMissingError); ok {
pub, errPub := ParsePublicKey(w.PubKey)
if errPub != nil {
return nil, fmt.Errorf("ssh: failed to parse embedded public key: %v", errPub)
}
err.PublicKey = pub
}
return nil, err
} }
pk1 := struct { pk1 := struct {
@ -1318,13 +998,15 @@ func parseOpenSSHPrivateKey(key []byte, decrypt openSSHDecryptFunc) (crypto.Priv
Rest []byte `ssh:"rest"` Rest []byte `ssh:"rest"`
}{} }{}
if err := Unmarshal(privKeyBlock, &pk1); err != nil || pk1.Check1 != pk1.Check2 { if err := Unmarshal(w.PrivKeyBlock, &pk1); err != nil {
if w.CipherName != "none" { return nil, err
return nil, x509.IncorrectPasswordError
}
return nil, errors.New("ssh: malformed OpenSSH key")
} }
if pk1.Check1 != pk1.Check2 {
return nil, errors.New("ssh: checkint mismatch")
}
// we only handle ed25519 and rsa keys currently
switch pk1.Keytype { switch pk1.Keytype {
case KeyAlgoRSA: case KeyAlgoRSA:
// https://github.com/openssh/openssh-portable/blob/master/sshkey.c#L2760-L2773 // https://github.com/openssh/openssh-portable/blob/master/sshkey.c#L2760-L2773
@ -1343,8 +1025,10 @@ func parseOpenSSHPrivateKey(key []byte, decrypt openSSHDecryptFunc) (crypto.Priv
return nil, err return nil, err
} }
if err := checkOpenSSHKeyPadding(key.Pad); err != nil { for i, b := range key.Pad {
return nil, err if int(b) != i+1 {
return nil, errors.New("ssh: padding not as expected")
}
} }
pk := &rsa.PrivateKey{ pk := &rsa.PrivateKey{
@ -1379,78 +1063,20 @@ func parseOpenSSHPrivateKey(key []byte, decrypt openSSHDecryptFunc) (crypto.Priv
return nil, errors.New("ssh: private key unexpected length") return nil, errors.New("ssh: private key unexpected length")
} }
if err := checkOpenSSHKeyPadding(key.Pad); err != nil { for i, b := range key.Pad {
return nil, err if int(b) != i+1 {
return nil, errors.New("ssh: padding not as expected")
}
} }
pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize)) pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize))
copy(pk, key.Priv) copy(pk, key.Priv)
return &pk, nil return &pk, nil
case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521:
key := struct {
Curve string
Pub []byte
D *big.Int
Comment string
Pad []byte `ssh:"rest"`
}{}
if err := Unmarshal(pk1.Rest, &key); err != nil {
return nil, err
}
if err := checkOpenSSHKeyPadding(key.Pad); err != nil {
return nil, err
}
var curve elliptic.Curve
switch key.Curve {
case "nistp256":
curve = elliptic.P256()
case "nistp384":
curve = elliptic.P384()
case "nistp521":
curve = elliptic.P521()
default:
return nil, errors.New("ssh: unhandled elliptic curve: " + key.Curve)
}
X, Y := elliptic.Unmarshal(curve, key.Pub)
if X == nil || Y == nil {
return nil, errors.New("ssh: failed to unmarshal public key")
}
if key.D.Cmp(curve.Params().N) >= 0 {
return nil, errors.New("ssh: scalar is out of range")
}
x, y := curve.ScalarBaseMult(key.D.Bytes())
if x.Cmp(X) != 0 || y.Cmp(Y) != 0 {
return nil, errors.New("ssh: public key does not match private key")
}
return &ecdsa.PrivateKey{
PublicKey: ecdsa.PublicKey{
Curve: curve,
X: X,
Y: Y,
},
D: key.D,
}, nil
default: default:
return nil, errors.New("ssh: unhandled key type") return nil, errors.New("ssh: unhandled key type")
} }
} }
func checkOpenSSHKeyPadding(pad []byte) error {
for i, b := range pad {
if int(b) != i+1 {
return errors.New("ssh: padding not as expected")
}
}
return nil
}
// FingerprintLegacyMD5 returns the user presentation of the key's // FingerprintLegacyMD5 returns the user presentation of the key's
// fingerprint as described by RFC 4716 section 4. // fingerprint as described by RFC 4716 section 4.
func FingerprintLegacyMD5(pubKey PublicKey) string { func FingerprintLegacyMD5(pubKey PublicKey) string {

View File

@ -97,36 +97,6 @@ type kexDHReplyMsg struct {
Signature []byte Signature []byte
} }
// See RFC 4419, section 5.
const msgKexDHGexGroup = 31
type kexDHGexGroupMsg struct {
P *big.Int `sshtype:"31"`
G *big.Int
}
const msgKexDHGexInit = 32
type kexDHGexInitMsg struct {
X *big.Int `sshtype:"32"`
}
const msgKexDHGexReply = 33
type kexDHGexReplyMsg struct {
HostKey []byte `sshtype:"33"`
Y *big.Int
Signature []byte
}
const msgKexDHGexRequest = 34
type kexDHGexRequestMsg struct {
MinBits uint32 `sshtype:"34"`
PreferedBits uint32
MaxBits uint32
}
// See RFC 4253, section 10. // See RFC 4253, section 10.
const msgServiceRequest = 5 const msgServiceRequest = 5
@ -305,42 +275,6 @@ type userAuthPubKeyOkMsg struct {
PubKey []byte PubKey []byte
} }
// See RFC 4462, section 3
const msgUserAuthGSSAPIResponse = 60
type userAuthGSSAPIResponse struct {
SupportMech []byte `sshtype:"60"`
}
const msgUserAuthGSSAPIToken = 61
type userAuthGSSAPIToken struct {
Token []byte `sshtype:"61"`
}
const msgUserAuthGSSAPIMIC = 66
type userAuthGSSAPIMIC struct {
MIC []byte `sshtype:"66"`
}
// See RFC 4462, section 3.9
const msgUserAuthGSSAPIErrTok = 64
type userAuthGSSAPIErrTok struct {
ErrorToken []byte `sshtype:"64"`
}
// See RFC 4462, section 3.8
const msgUserAuthGSSAPIError = 65
type userAuthGSSAPIError struct {
MajorStatus uint32 `sshtype:"65"`
MinorStatus uint32
Message string
LanguageTag string
}
// typeTags returns the possible type bytes for the given reflect.Type, which // typeTags returns the possible type bytes for the given reflect.Type, which
// should be a struct. The possible values are separated by a '|' character. // should be a struct. The possible values are separated by a '|' character.
func typeTags(structType reflect.Type) (tags []byte) { func typeTags(structType reflect.Type) (tags []byte) {
@ -822,14 +756,6 @@ func decode(packet []byte) (interface{}, error) {
msg = new(channelRequestSuccessMsg) msg = new(channelRequestSuccessMsg)
case msgChannelFailure: case msgChannelFailure:
msg = new(channelRequestFailureMsg) msg = new(channelRequestFailureMsg)
case msgUserAuthGSSAPIToken:
msg = new(userAuthGSSAPIToken)
case msgUserAuthGSSAPIMIC:
msg = new(userAuthGSSAPIMIC)
case msgUserAuthGSSAPIErrTok:
msg = new(userAuthGSSAPIErrTok)
case msgUserAuthGSSAPIError:
msg = new(userAuthGSSAPIError)
default: default:
return nil, unexpectedMessageError(0, packet[0]) return nil, unexpectedMessageError(0, packet[0])
} }
@ -838,29 +764,3 @@ func decode(packet []byte) (interface{}, error) {
} }
return msg, nil return msg, nil
} }
var packetTypeNames = map[byte]string{
msgDisconnect: "disconnectMsg",
msgServiceRequest: "serviceRequestMsg",
msgServiceAccept: "serviceAcceptMsg",
msgKexInit: "kexInitMsg",
msgKexDHInit: "kexDHInitMsg",
msgKexDHReply: "kexDHReplyMsg",
msgUserAuthRequest: "userAuthRequestMsg",
msgUserAuthSuccess: "userAuthSuccessMsg",
msgUserAuthFailure: "userAuthFailureMsg",
msgUserAuthPubKeyOk: "userAuthPubKeyOkMsg",
msgGlobalRequest: "globalRequestMsg",
msgRequestSuccess: "globalRequestSuccessMsg",
msgRequestFailure: "globalRequestFailureMsg",
msgChannelOpen: "channelOpenMsg",
msgChannelData: "channelDataMsg",
msgChannelOpenConfirm: "channelOpenConfirmMsg",
msgChannelOpenFailure: "channelOpenFailureMsg",
msgChannelWindowAdjust: "windowAdjustMsg",
msgChannelEOF: "channelEOFMsg",
msgChannelClose: "channelCloseMsg",
msgChannelRequest: "channelRequestMsg",
msgChannelSuccess: "channelRequestSuccessMsg",
msgChannelFailure: "channelRequestFailureMsg",
}

View File

@ -240,7 +240,7 @@ func (m *mux) onePacket() error {
id := binary.BigEndian.Uint32(packet[1:]) id := binary.BigEndian.Uint32(packet[1:])
ch := m.chanList.getChan(id) ch := m.chanList.getChan(id)
if ch == nil { if ch == nil {
return m.handleUnknownChannelPacket(id, packet) return fmt.Errorf("ssh: invalid channel %d", id)
} }
return ch.handlePacket(packet) return ch.handlePacket(packet)
@ -328,24 +328,3 @@ func (m *mux) openChannel(chanType string, extra []byte) (*channel, error) {
return nil, fmt.Errorf("ssh: unexpected packet in response to channel open: %T", msg) return nil, fmt.Errorf("ssh: unexpected packet in response to channel open: %T", msg)
} }
} }
func (m *mux) handleUnknownChannelPacket(id uint32, packet []byte) error {
msg, err := decode(packet)
if err != nil {
return err
}
switch msg := msg.(type) {
// RFC 4254 section 5.4 says unrecognized channel requests should
// receive a failure response.
case *channelRequestMsg:
if msg.WantReply {
return m.sendMessage(channelRequestFailureMsg{
PeersID: msg.PeersID,
})
}
return nil
default:
return fmt.Errorf("ssh: invalid channel %d", id)
}
}

View File

@ -45,20 +45,6 @@ type Permissions struct {
Extensions map[string]string Extensions map[string]string
} }
type GSSAPIWithMICConfig struct {
// AllowLogin, must be set, is called when gssapi-with-mic
// authentication is selected (RFC 4462 section 3). The srcName is from the
// results of the GSS-API authentication. The format is username@DOMAIN.
// GSSAPI just guarantees to the server who the user is, but not if they can log in, and with what permissions.
// This callback is called after the user identity is established with GSSAPI to decide if the user can login with
// which permissions. If the user is allowed to login, it should return a nil error.
AllowLogin func(conn ConnMetadata, srcName string) (*Permissions, error)
// Server must be set. It's the implementation
// of the GSSAPIServer interface. See GSSAPIServer interface for details.
Server GSSAPIServer
}
// ServerConfig holds server specific configuration data. // ServerConfig holds server specific configuration data.
type ServerConfig struct { type ServerConfig struct {
// Config contains configuration shared between client and server. // Config contains configuration shared between client and server.
@ -113,10 +99,6 @@ type ServerConfig struct {
// BannerCallback, if present, is called and the return string is sent to // BannerCallback, if present, is called and the return string is sent to
// the client after key exchange completed but before authentication. // the client after key exchange completed but before authentication.
BannerCallback func(conn ConnMetadata) string BannerCallback func(conn ConnMetadata) string
// GSSAPIWithMICConfig includes gssapi server and callback, which if both non-nil, is used
// when gssapi-with-mic authentication is selected (RFC 4462 section 3).
GSSAPIWithMICConfig *GSSAPIWithMICConfig
} }
// AddHostKey adds a private key as a host key. If an existing host // AddHostKey adds a private key as a host key. If an existing host
@ -193,12 +175,6 @@ func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewCha
if fullConf.MaxAuthTries == 0 { if fullConf.MaxAuthTries == 0 {
fullConf.MaxAuthTries = 6 fullConf.MaxAuthTries = 6
} }
// Check if the config contains any unsupported key exchanges
for _, kex := range fullConf.KeyExchanges {
if _, ok := serverForbiddenKexAlgos[kex]; ok {
return nil, nil, nil, fmt.Errorf("ssh: unsupported key exchange %s for server", kex)
}
}
s := &connection{ s := &connection{
sshConn: sshConn{conn: c}, sshConn: sshConn{conn: c},
@ -228,9 +204,7 @@ func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error)
return nil, errors.New("ssh: server has no host keys") return nil, errors.New("ssh: server has no host keys")
} }
if !config.NoClientAuth && config.PasswordCallback == nil && config.PublicKeyCallback == nil && if !config.NoClientAuth && config.PasswordCallback == nil && config.PublicKeyCallback == nil && config.KeyboardInteractiveCallback == nil {
config.KeyboardInteractiveCallback == nil && (config.GSSAPIWithMICConfig == nil ||
config.GSSAPIWithMICConfig.AllowLogin == nil || config.GSSAPIWithMICConfig.Server == nil) {
return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false") return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false")
} }
@ -284,8 +258,8 @@ func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error)
func isAcceptableAlgo(algo string) bool { func isAcceptableAlgo(algo string) bool {
switch algo { switch algo {
case KeyAlgoRSA, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, KeyAlgoSKECDSA256, KeyAlgoED25519, KeyAlgoSKED25519, case KeyAlgoRSA, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, KeyAlgoED25519,
CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoSKECDSA256v01, CertAlgoED25519v01, CertAlgoSKED25519v01: CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01:
return true return true
} }
return false return false
@ -321,55 +295,6 @@ func checkSourceAddress(addr net.Addr, sourceAddrs string) error {
return fmt.Errorf("ssh: remote address %v is not allowed because of source-address restriction", addr) return fmt.Errorf("ssh: remote address %v is not allowed because of source-address restriction", addr)
} }
func gssExchangeToken(gssapiConfig *GSSAPIWithMICConfig, firstToken []byte, s *connection,
sessionID []byte, userAuthReq userAuthRequestMsg) (authErr error, perms *Permissions, err error) {
gssAPIServer := gssapiConfig.Server
defer gssAPIServer.DeleteSecContext()
var srcName string
for {
var (
outToken []byte
needContinue bool
)
outToken, srcName, needContinue, err = gssAPIServer.AcceptSecContext(firstToken)
if err != nil {
return err, nil, nil
}
if len(outToken) != 0 {
if err := s.transport.writePacket(Marshal(&userAuthGSSAPIToken{
Token: outToken,
})); err != nil {
return nil, nil, err
}
}
if !needContinue {
break
}
packet, err := s.transport.readPacket()
if err != nil {
return nil, nil, err
}
userAuthGSSAPITokenReq := &userAuthGSSAPIToken{}
if err := Unmarshal(packet, userAuthGSSAPITokenReq); err != nil {
return nil, nil, err
}
}
packet, err := s.transport.readPacket()
if err != nil {
return nil, nil, err
}
userAuthGSSAPIMICReq := &userAuthGSSAPIMIC{}
if err := Unmarshal(packet, userAuthGSSAPIMICReq); err != nil {
return nil, nil, err
}
mic := buildMIC(string(sessionID), userAuthReq.User, userAuthReq.Service, userAuthReq.Method)
if err := gssAPIServer.VerifyMIC(mic, userAuthGSSAPIMICReq.MIC); err != nil {
return err, nil, nil
}
perms, authErr = gssapiConfig.AllowLogin(s, srcName)
return authErr, perms, nil
}
// ServerAuthError represents server authentication errors and is // ServerAuthError represents server authentication errors and is
// sometimes returned by NewServerConn. It appends any authentication // sometimes returned by NewServerConn. It appends any authentication
// errors that may occur, and is returned if all of the authentication // errors that may occur, and is returned if all of the authentication
@ -571,49 +496,6 @@ userAuthLoop:
authErr = candidate.result authErr = candidate.result
perms = candidate.perms perms = candidate.perms
} }
case "gssapi-with-mic":
gssapiConfig := config.GSSAPIWithMICConfig
userAuthRequestGSSAPI, err := parseGSSAPIPayload(userAuthReq.Payload)
if err != nil {
return nil, parseError(msgUserAuthRequest)
}
// OpenSSH supports Kerberos V5 mechanism only for GSS-API authentication.
if userAuthRequestGSSAPI.N == 0 {
authErr = fmt.Errorf("ssh: Mechanism negotiation is not supported")
break
}
var i uint32
present := false
for i = 0; i < userAuthRequestGSSAPI.N; i++ {
if userAuthRequestGSSAPI.OIDS[i].Equal(krb5Mesh) {
present = true
break
}
}
if !present {
authErr = fmt.Errorf("ssh: GSSAPI authentication must use the Kerberos V5 mechanism")
break
}
// Initial server response, see RFC 4462 section 3.3.
if err := s.transport.writePacket(Marshal(&userAuthGSSAPIResponse{
SupportMech: krb5OID,
})); err != nil {
return nil, err
}
// Exchange token, see RFC 4462 section 3.4.
packet, err := s.transport.readPacket()
if err != nil {
return nil, err
}
userAuthGSSAPITokenReq := &userAuthGSSAPIToken{}
if err := Unmarshal(packet, userAuthGSSAPITokenReq); err != nil {
return nil, err
}
authErr, perms, err = gssExchangeToken(gssapiConfig, userAuthGSSAPITokenReq.Token, s, sessionID,
userAuthReq)
if err != nil {
return nil, err
}
default: default:
authErr = fmt.Errorf("ssh: unknown method %q", userAuthReq.Method) authErr = fmt.Errorf("ssh: unknown method %q", userAuthReq.Method)
} }
@ -640,10 +522,6 @@ userAuthLoop:
if config.KeyboardInteractiveCallback != nil { if config.KeyboardInteractiveCallback != nil {
failureMsg.Methods = append(failureMsg.Methods, "keyboard-interactive") failureMsg.Methods = append(failureMsg.Methods, "keyboard-interactive")
} }
if config.GSSAPIWithMICConfig != nil && config.GSSAPIWithMICConfig.Server != nil &&
config.GSSAPIWithMICConfig.AllowLogin != nil {
failureMsg.Methods = append(failureMsg.Methods, "gssapi-with-mic")
}
if len(failureMsg.Methods) == 0 { if len(failureMsg.Methods) == 0 {
return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false") return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false")

View File

@ -1,139 +0,0 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ssh
import (
"encoding/asn1"
"errors"
)
var krb5OID []byte
func init() {
krb5OID, _ = asn1.Marshal(krb5Mesh)
}
// GSSAPIClient provides the API to plug-in GSSAPI authentication for client logins.
type GSSAPIClient interface {
// InitSecContext initiates the establishment of a security context for GSS-API between the
// ssh client and ssh server. Initially the token parameter should be specified as nil.
// The routine may return a outputToken which should be transferred to
// the ssh server, where the ssh server will present it to
// AcceptSecContext. If no token need be sent, InitSecContext will indicate this by setting
// needContinue to false. To complete the context
// establishment, one or more reply tokens may be required from the ssh
// server;if so, InitSecContext will return a needContinue which is true.
// In this case, InitSecContext should be called again when the
// reply token is received from the ssh server, passing the reply
// token to InitSecContext via the token parameters.
// See RFC 2743 section 2.2.1 and RFC 4462 section 3.4.
InitSecContext(target string, token []byte, isGSSDelegCreds bool) (outputToken []byte, needContinue bool, err error)
// GetMIC generates a cryptographic MIC for the SSH2 message, and places
// the MIC in a token for transfer to the ssh server.
// The contents of the MIC field are obtained by calling GSS_GetMIC()
// over the following, using the GSS-API context that was just
// established:
// string session identifier
// byte SSH_MSG_USERAUTH_REQUEST
// string user name
// string service
// string "gssapi-with-mic"
// See RFC 2743 section 2.3.1 and RFC 4462 3.5.
GetMIC(micFiled []byte) ([]byte, error)
// Whenever possible, it should be possible for
// DeleteSecContext() calls to be successfully processed even
// if other calls cannot succeed, thereby enabling context-related
// resources to be released.
// In addition to deleting established security contexts,
// gss_delete_sec_context must also be able to delete "half-built"
// security contexts resulting from an incomplete sequence of
// InitSecContext()/AcceptSecContext() calls.
// See RFC 2743 section 2.2.3.
DeleteSecContext() error
}
// GSSAPIServer provides the API to plug in GSSAPI authentication for server logins.
type GSSAPIServer interface {
// AcceptSecContext allows a remotely initiated security context between the application
// and a remote peer to be established by the ssh client. The routine may return a
// outputToken which should be transferred to the ssh client,
// where the ssh client will present it to InitSecContext.
// If no token need be sent, AcceptSecContext will indicate this
// by setting the needContinue to false. To
// complete the context establishment, one or more reply tokens may be
// required from the ssh client. if so, AcceptSecContext
// will return a needContinue which is true, in which case it
// should be called again when the reply token is received from the ssh
// client, passing the token to AcceptSecContext via the
// token parameters.
// The srcName return value is the authenticated username.
// See RFC 2743 section 2.2.2 and RFC 4462 section 3.4.
AcceptSecContext(token []byte) (outputToken []byte, srcName string, needContinue bool, err error)
// VerifyMIC verifies that a cryptographic MIC, contained in the token parameter,
// fits the supplied message is received from the ssh client.
// See RFC 2743 section 2.3.2.
VerifyMIC(micField []byte, micToken []byte) error
// Whenever possible, it should be possible for
// DeleteSecContext() calls to be successfully processed even
// if other calls cannot succeed, thereby enabling context-related
// resources to be released.
// In addition to deleting established security contexts,
// gss_delete_sec_context must also be able to delete "half-built"
// security contexts resulting from an incomplete sequence of
// InitSecContext()/AcceptSecContext() calls.
// See RFC 2743 section 2.2.3.
DeleteSecContext() error
}
var (
// OpenSSH supports Kerberos V5 mechanism only for GSS-API authentication,
// so we also support the krb5 mechanism only.
// See RFC 1964 section 1.
krb5Mesh = asn1.ObjectIdentifier{1, 2, 840, 113554, 1, 2, 2}
)
// The GSS-API authentication method is initiated when the client sends an SSH_MSG_USERAUTH_REQUEST
// See RFC 4462 section 3.2.
type userAuthRequestGSSAPI struct {
N uint32
OIDS []asn1.ObjectIdentifier
}
func parseGSSAPIPayload(payload []byte) (*userAuthRequestGSSAPI, error) {
n, rest, ok := parseUint32(payload)
if !ok {
return nil, errors.New("parse uint32 failed")
}
s := &userAuthRequestGSSAPI{
N: n,
OIDS: make([]asn1.ObjectIdentifier, n),
}
for i := 0; i < int(n); i++ {
var (
desiredMech []byte
err error
)
desiredMech, rest, ok = parseString(rest)
if !ok {
return nil, errors.New("parse string failed")
}
if rest, err = asn1.Unmarshal(desiredMech, &s.OIDS[i]); err != nil {
return nil, err
}
}
return s, nil
}
// See RFC 4462 section 3.6.
func buildMIC(sessionID string, username string, service string, authMethod string) []byte {
out := make([]byte, 0, 0)
out = appendString(out, sessionID)
out = append(out, msgUserAuthRequest)
out = appendString(out, username)
out = appendString(out, service)
out = appendString(out, authMethod)
return out
}

View File

@ -7,8 +7,6 @@ package terminal
import ( import (
"bytes" "bytes"
"io" "io"
"runtime"
"strconv"
"sync" "sync"
"unicode/utf8" "unicode/utf8"
) )
@ -113,7 +111,6 @@ func NewTerminal(c io.ReadWriter, prompt string) *Terminal {
} }
const ( const (
keyCtrlC = 3
keyCtrlD = 4 keyCtrlD = 4
keyCtrlU = 21 keyCtrlU = 21
keyEnter = '\r' keyEnter = '\r'
@ -152,12 +149,8 @@ func bytesToKey(b []byte, pasteActive bool) (rune, []byte) {
switch b[0] { switch b[0] {
case 1: // ^A case 1: // ^A
return keyHome, b[1:] return keyHome, b[1:]
case 2: // ^B
return keyLeft, b[1:]
case 5: // ^E case 5: // ^E
return keyEnd, b[1:] return keyEnd, b[1:]
case 6: // ^F
return keyRight, b[1:]
case 8: // ^H case 8: // ^H
return keyBackspace, b[1:] return keyBackspace, b[1:]
case 11: // ^K case 11: // ^K
@ -278,44 +271,34 @@ func (t *Terminal) moveCursorToPos(pos int) {
} }
func (t *Terminal) move(up, down, left, right int) { func (t *Terminal) move(up, down, left, right int) {
m := []rune{} movement := make([]rune, 3*(up+down+left+right))
m := movement
// 1 unit up can be expressed as ^[[A or ^[A for i := 0; i < up; i++ {
// 5 units up can be expressed as ^[[5A m[0] = keyEscape
m[1] = '['
if up == 1 { m[2] = 'A'
m = append(m, keyEscape, '[', 'A') m = m[3:]
} else if up > 1 { }
m = append(m, keyEscape, '[') for i := 0; i < down; i++ {
m = append(m, []rune(strconv.Itoa(up))...) m[0] = keyEscape
m = append(m, 'A') m[1] = '['
m[2] = 'B'
m = m[3:]
}
for i := 0; i < left; i++ {
m[0] = keyEscape
m[1] = '['
m[2] = 'D'
m = m[3:]
}
for i := 0; i < right; i++ {
m[0] = keyEscape
m[1] = '['
m[2] = 'C'
m = m[3:]
} }
if down == 1 { t.queue(movement)
m = append(m, keyEscape, '[', 'B')
} else if down > 1 {
m = append(m, keyEscape, '[')
m = append(m, []rune(strconv.Itoa(down))...)
m = append(m, 'B')
}
if right == 1 {
m = append(m, keyEscape, '[', 'C')
} else if right > 1 {
m = append(m, keyEscape, '[')
m = append(m, []rune(strconv.Itoa(right))...)
m = append(m, 'C')
}
if left == 1 {
m = append(m, keyEscape, '[', 'D')
} else if left > 1 {
m = append(m, keyEscape, '[')
m = append(m, []rune(strconv.Itoa(left))...)
m = append(m, 'D')
}
t.queue(m)
} }
func (t *Terminal) clearLineToRight() { func (t *Terminal) clearLineToRight() {
@ -743,9 +726,6 @@ func (t *Terminal) readLine() (line string, err error) {
return "", io.EOF return "", io.EOF
} }
} }
if key == keyCtrlC {
return "", io.EOF
}
if key == keyPasteStart { if key == keyPasteStart {
t.pasteActive = true t.pasteActive = true
if len(t.line) == 0 { if len(t.line) == 0 {
@ -948,8 +928,6 @@ func (s *stRingBuffer) NthPreviousEntry(n int) (value string, ok bool) {
// readPasswordLine reads from reader until it finds \n or io.EOF. // readPasswordLine reads from reader until it finds \n or io.EOF.
// The slice returned does not include the \n. // The slice returned does not include the \n.
// readPasswordLine also ignores any \r it finds. // readPasswordLine also ignores any \r it finds.
// Windows uses \r as end of line. So, on Windows, readPasswordLine
// reads until it finds \r and ignores any \n it finds during processing.
func readPasswordLine(reader io.Reader) ([]byte, error) { func readPasswordLine(reader io.Reader) ([]byte, error) {
var buf [1]byte var buf [1]byte
var ret []byte var ret []byte
@ -958,20 +936,10 @@ func readPasswordLine(reader io.Reader) ([]byte, error) {
n, err := reader.Read(buf[:]) n, err := reader.Read(buf[:])
if n > 0 { if n > 0 {
switch buf[0] { switch buf[0] {
case '\b':
if len(ret) > 0 {
ret = ret[:len(ret)-1]
}
case '\n': case '\n':
if runtime.GOOS != "windows" { return ret, nil
return ret, nil
}
// otherwise ignore \n
case '\r': case '\r':
if runtime.GOOS == "windows" { // remove \r from passwords on Windows
return ret, nil
}
// otherwise ignore \r
default: default:
ret = append(ret, buf[0]) ret = append(ret, buf[0])
} }

View File

@ -85,8 +85,8 @@ func ReadPassword(fd int) ([]byte, error) {
} }
old := st old := st
st &^= (windows.ENABLE_ECHO_INPUT | windows.ENABLE_LINE_INPUT) st &^= (windows.ENABLE_ECHO_INPUT)
st |= (windows.ENABLE_PROCESSED_OUTPUT | windows.ENABLE_PROCESSED_INPUT) st |= (windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT)
if err := windows.SetConsoleMode(windows.Handle(fd), st); err != nil { if err := windows.SetConsoleMode(windows.Handle(fd), st); err != nil {
return nil, err return nil, err
} }

View File

@ -53,14 +53,14 @@ type transport struct {
// packetCipher represents a combination of SSH encryption/MAC // packetCipher represents a combination of SSH encryption/MAC
// protocol. A single instance should be used for one direction only. // protocol. A single instance should be used for one direction only.
type packetCipher interface { type packetCipher interface {
// writeCipherPacket encrypts the packet and writes it to w. The // writePacket encrypts the packet and writes it to w. The
// contents of the packet are generally scrambled. // contents of the packet are generally scrambled.
writeCipherPacket(seqnum uint32, w io.Writer, rand io.Reader, packet []byte) error writePacket(seqnum uint32, w io.Writer, rand io.Reader, packet []byte) error
// readCipherPacket reads and decrypts a packet of data. The // readPacket reads and decrypts a packet of data. The
// returned packet may be overwritten by future calls of // returned packet may be overwritten by future calls of
// readPacket. // readPacket.
readCipherPacket(seqnum uint32, r io.Reader) ([]byte, error) readPacket(seqnum uint32, r io.Reader) ([]byte, error)
} }
// connectionState represents one side (read or write) of the // connectionState represents one side (read or write) of the
@ -127,7 +127,7 @@ func (t *transport) readPacket() (p []byte, err error) {
} }
func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) { func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) {
packet, err := s.packetCipher.readCipherPacket(s.seqNum, r) packet, err := s.packetCipher.readPacket(s.seqNum, r)
s.seqNum++ s.seqNum++
if err == nil && len(packet) == 0 { if err == nil && len(packet) == 0 {
err = errors.New("ssh: zero length packet") err = errors.New("ssh: zero length packet")
@ -175,7 +175,7 @@ func (t *transport) writePacket(packet []byte) error {
func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte) error { func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte) error {
changeKeys := len(packet) > 0 && packet[0] == msgNewKeys changeKeys := len(packet) > 0 && packet[0] == msgNewKeys
err := s.packetCipher.writeCipherPacket(s.seqNum, w, rand, packet) err := s.packetCipher.writePacket(s.seqNum, w, rand, packet)
if err != nil { if err != nil {
return err return err
} }

View File

@ -52,6 +52,7 @@ var isSpecialElementMap = map[string]bool{
"iframe": true, "iframe": true,
"img": true, "img": true,
"input": true, "input": true,
"isindex": true, // The 'isindex' element has been removed, but keep it for backwards compatibility.
"keygen": true, "keygen": true,
"li": true, "li": true,
"link": true, "link": true,

View File

@ -172,6 +172,7 @@ var svgAttributeAdjustments = map[string]string{
"diffuseconstant": "diffuseConstant", "diffuseconstant": "diffuseConstant",
"edgemode": "edgeMode", "edgemode": "edgeMode",
"externalresourcesrequired": "externalResourcesRequired", "externalresourcesrequired": "externalResourcesRequired",
"filterres": "filterRes",
"filterunits": "filterUnits", "filterunits": "filterUnits",
"glyphref": "glyphRef", "glyphref": "glyphRef",
"gradienttransform": "gradientTransform", "gradienttransform": "gradientTransform",

View File

@ -18,11 +18,6 @@ const (
ElementNode ElementNode
CommentNode CommentNode
DoctypeNode DoctypeNode
// RawNode nodes are not returned by the parser, but can be part of the
// Node tree passed to func Render to insert raw HTML (without escaping).
// If so, this package makes no guarantee that the rendered HTML is secure
// (from e.g. Cross Site Scripting attacks) or well-formed.
RawNode
scopeMarkerNode scopeMarkerNode
) )

304
vendor/golang.org/x/net/html/parse.go generated vendored
View File

@ -184,17 +184,6 @@ func (p *parser) clearStackToContext(s scope) {
} }
} }
// parseGenericRawTextElements implements the generic raw text element parsing
// algorithm defined in 12.2.6.2.
// https://html.spec.whatwg.org/multipage/parsing.html#parsing-elements-that-contain-only-text
// TODO: Since both RAWTEXT and RCDATA states are treated as tokenizer's part
// officially, need to make tokenizer consider both states.
func (p *parser) parseGenericRawTextElement() {
p.addElement()
p.originalIM = p.im
p.im = textIM
}
// generateImpliedEndTags pops nodes off the stack of open elements as long as // generateImpliedEndTags pops nodes off the stack of open elements as long as
// the top node has a tag name of dd, dt, li, optgroup, option, p, rb, rp, rt or rtc. // the top node has a tag name of dd, dt, li, optgroup, option, p, rb, rp, rt or rtc.
// If exceptions are specified, nodes with that name will not be popped off. // If exceptions are specified, nodes with that name will not be popped off.
@ -203,17 +192,16 @@ func (p *parser) generateImpliedEndTags(exceptions ...string) {
loop: loop:
for i = len(p.oe) - 1; i >= 0; i-- { for i = len(p.oe) - 1; i >= 0; i-- {
n := p.oe[i] n := p.oe[i]
if n.Type != ElementNode { if n.Type == ElementNode {
break switch n.DataAtom {
} case a.Dd, a.Dt, a.Li, a.Optgroup, a.Option, a.P, a.Rb, a.Rp, a.Rt, a.Rtc:
switch n.DataAtom { for _, except := range exceptions {
case a.Dd, a.Dt, a.Li, a.Optgroup, a.Option, a.P, a.Rb, a.Rp, a.Rt, a.Rtc: if n.Data == except {
for _, except := range exceptions { break loop
if n.Data == except { }
break loop
} }
continue
} }
continue
} }
break break
} }
@ -381,7 +369,8 @@ findIdenticalElements:
// Section 12.2.4.3. // Section 12.2.4.3.
func (p *parser) clearActiveFormattingElements() { func (p *parser) clearActiveFormattingElements() {
for { for {
if n := p.afe.pop(); len(p.afe) == 0 || n.Type == scopeMarkerNode { n := p.afe.pop()
if len(p.afe) == 0 || n.Type == scopeMarkerNode {
return return
} }
} }
@ -636,29 +625,25 @@ func inHeadIM(p *parser) bool {
switch p.tok.DataAtom { switch p.tok.DataAtom {
case a.Html: case a.Html:
return inBodyIM(p) return inBodyIM(p)
case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta: case a.Base, a.Basefont, a.Bgsound, a.Command, a.Link, a.Meta:
p.addElement() p.addElement()
p.oe.pop() p.oe.pop()
p.acknowledgeSelfClosingTag() p.acknowledgeSelfClosingTag()
return true return true
case a.Noscript: case a.Noscript:
if p.scripting {
p.parseGenericRawTextElement()
return true
}
p.addElement() p.addElement()
p.im = inHeadNoscriptIM if p.scripting {
// Don't let the tokenizer go into raw text mode when scripting is disabled. p.setOriginalIM()
p.tokenizer.NextIsNotRawText() p.im = textIM
} else {
p.im = inHeadNoscriptIM
}
return true return true
case a.Script, a.Title: case a.Script, a.Title, a.Noframes, a.Style:
p.addElement() p.addElement()
p.setOriginalIM() p.setOriginalIM()
p.im = textIM p.im = textIM
return true return true
case a.Noframes, a.Style:
p.parseGenericRawTextElement()
return true
case a.Head: case a.Head:
// Ignore the token. // Ignore the token.
return true return true
@ -870,7 +855,7 @@ func inBodyIM(p *parser) bool {
return true return true
} }
copyAttributes(p.oe[0], p.tok) copyAttributes(p.oe[0], p.tok)
case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Template, a.Title: case a.Base, a.Basefont, a.Bgsound, a.Command, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Template, a.Title:
return inHeadIM(p) return inHeadIM(p)
case a.Body: case a.Body:
if p.oe.contains(a.Template) { if p.oe.contains(a.Template) {
@ -896,7 +881,7 @@ func inBodyIM(p *parser) bool {
p.addElement() p.addElement()
p.im = inFramesetIM p.im = inFramesetIM
return true return true
case a.Address, a.Article, a.Aside, a.Blockquote, a.Center, a.Details, a.Dialog, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Main, a.Menu, a.Nav, a.Ol, a.P, a.Section, a.Summary, a.Ul: case a.Address, a.Article, a.Aside, a.Blockquote, a.Center, a.Details, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Menu, a.Nav, a.Ol, a.P, a.Section, a.Summary, a.Ul:
p.popUntil(buttonScope, a.P) p.popUntil(buttonScope, a.P)
p.addElement() p.addElement()
case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6: case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
@ -1029,6 +1014,53 @@ func inBodyIM(p *parser) bool {
p.tok.DataAtom = a.Img p.tok.DataAtom = a.Img
p.tok.Data = a.Img.String() p.tok.Data = a.Img.String()
return false return false
case a.Isindex:
if p.form != nil {
// Ignore the token.
return true
}
action := ""
prompt := "This is a searchable index. Enter search keywords: "
attr := []Attribute{{Key: "name", Val: "isindex"}}
for _, t := range p.tok.Attr {
switch t.Key {
case "action":
action = t.Val
case "name":
// Ignore the attribute.
case "prompt":
prompt = t.Val
default:
attr = append(attr, t)
}
}
p.acknowledgeSelfClosingTag()
p.popUntil(buttonScope, a.P)
p.parseImpliedToken(StartTagToken, a.Form, a.Form.String())
if p.form == nil {
// NOTE: The 'isindex' element has been removed,
// and the 'template' element has not been designed to be
// collaborative with the index element.
//
// Ignore the token.
return true
}
if action != "" {
p.form.Attr = []Attribute{{Key: "action", Val: action}}
}
p.parseImpliedToken(StartTagToken, a.Hr, a.Hr.String())
p.parseImpliedToken(StartTagToken, a.Label, a.Label.String())
p.addText(prompt)
p.addChild(&Node{
Type: ElementNode,
DataAtom: a.Input,
Data: a.Input.String(),
Attr: attr,
})
p.oe.pop()
p.parseImpliedToken(EndTagToken, a.Label, a.Label.String())
p.parseImpliedToken(StartTagToken, a.Hr, a.Hr.String())
p.parseImpliedToken(EndTagToken, a.Form, a.Form.String())
case a.Textarea: case a.Textarea:
p.addElement() p.addElement()
p.setOriginalIM() p.setOriginalIM()
@ -1038,21 +1070,18 @@ func inBodyIM(p *parser) bool {
p.popUntil(buttonScope, a.P) p.popUntil(buttonScope, a.P)
p.reconstructActiveFormattingElements() p.reconstructActiveFormattingElements()
p.framesetOK = false p.framesetOK = false
p.parseGenericRawTextElement() p.addElement()
p.setOriginalIM()
p.im = textIM
case a.Iframe: case a.Iframe:
p.framesetOK = false p.framesetOK = false
p.parseGenericRawTextElement()
case a.Noembed:
p.parseGenericRawTextElement()
case a.Noscript:
if p.scripting {
p.parseGenericRawTextElement()
return true
}
p.reconstructActiveFormattingElements()
p.addElement() p.addElement()
// Don't let the tokenizer go into raw text mode when scripting is disabled. p.setOriginalIM()
p.tokenizer.NextIsNotRawText() p.im = textIM
case a.Noembed, a.Noscript:
p.addElement()
p.setOriginalIM()
p.im = textIM
case a.Select: case a.Select:
p.reconstructActiveFormattingElements() p.reconstructActiveFormattingElements()
p.addElement() p.addElement()
@ -1108,7 +1137,7 @@ func inBodyIM(p *parser) bool {
return false return false
} }
return true return true
case a.Address, a.Article, a.Aside, a.Blockquote, a.Button, a.Center, a.Details, a.Dialog, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Listing, a.Main, a.Menu, a.Nav, a.Ol, a.Pre, a.Section, a.Summary, a.Ul: case a.Address, a.Article, a.Aside, a.Blockquote, a.Button, a.Center, a.Details, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Listing, a.Menu, a.Nav, a.Ol, a.Pre, a.Section, a.Summary, a.Ul:
p.popUntil(defaultScope, p.tok.DataAtom) p.popUntil(defaultScope, p.tok.DataAtom)
case a.Form: case a.Form:
if p.oe.contains(a.Template) { if p.oe.contains(a.Template) {
@ -1169,13 +1198,14 @@ func inBodyIM(p *parser) bool {
if len(p.templateStack) > 0 { if len(p.templateStack) > 0 {
p.im = inTemplateIM p.im = inTemplateIM
return false return false
} } else {
for _, e := range p.oe { for _, e := range p.oe {
switch e.DataAtom { switch e.DataAtom {
case a.Dd, a.Dt, a.Li, a.Optgroup, a.Option, a.P, a.Rb, a.Rp, a.Rt, a.Rtc, a.Tbody, a.Td, a.Tfoot, a.Th, case a.Dd, a.Dt, a.Li, a.Optgroup, a.Option, a.P, a.Rb, a.Rp, a.Rt, a.Rtc, a.Tbody, a.Td, a.Tfoot, a.Th,
a.Thead, a.Tr, a.Body, a.Html: a.Thead, a.Tr, a.Body, a.Html:
default: default:
return true return true
}
} }
} }
} }
@ -1191,15 +1221,9 @@ func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom, tagName string) {
// Once the code successfully parses the comprehensive test suite, we should // Once the code successfully parses the comprehensive test suite, we should
// refactor this code to be more idiomatic. // refactor this code to be more idiomatic.
// Steps 1-2 // Steps 1-4. The outer loop.
if current := p.oe.top(); current.Data == tagName && p.afe.index(current) == -1 {
p.oe.pop()
return
}
// Steps 3-5. The outer loop.
for i := 0; i < 8; i++ { for i := 0; i < 8; i++ {
// Step 6. Find the formatting element. // Step 5. Find the formatting element.
var formattingElement *Node var formattingElement *Node
for j := len(p.afe) - 1; j >= 0; j-- { for j := len(p.afe) - 1; j >= 0; j-- {
if p.afe[j].Type == scopeMarkerNode { if p.afe[j].Type == scopeMarkerNode {
@ -1214,22 +1238,17 @@ func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom, tagName string) {
p.inBodyEndTagOther(tagAtom, tagName) p.inBodyEndTagOther(tagAtom, tagName)
return return
} }
// Step 7. Ignore the tag if formatting element is not in the stack of open elements.
feIndex := p.oe.index(formattingElement) feIndex := p.oe.index(formattingElement)
if feIndex == -1 { if feIndex == -1 {
p.afe.remove(formattingElement) p.afe.remove(formattingElement)
return return
} }
// Step 8. Ignore the tag if formatting element is not in the scope.
if !p.elementInScope(defaultScope, tagAtom) { if !p.elementInScope(defaultScope, tagAtom) {
// Ignore the tag. // Ignore the tag.
return return
} }
// Step 9. This step is omitted because it's just a parse error but no need to return. // Steps 9-10. Find the furthest block.
// Steps 10-11. Find the furthest block.
var furthestBlock *Node var furthestBlock *Node
for _, e := range p.oe[feIndex:] { for _, e := range p.oe[feIndex:] {
if isSpecialElement(e) { if isSpecialElement(e) {
@ -1246,65 +1265,47 @@ func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom, tagName string) {
return return
} }
// Steps 12-13. Find the common ancestor and bookmark node. // Steps 11-12. Find the common ancestor and bookmark node.
commonAncestor := p.oe[feIndex-1] commonAncestor := p.oe[feIndex-1]
bookmark := p.afe.index(formattingElement) bookmark := p.afe.index(formattingElement)
// Step 14. The inner loop. Find the lastNode to reparent. // Step 13. The inner loop. Find the lastNode to reparent.
lastNode := furthestBlock lastNode := furthestBlock
node := furthestBlock node := furthestBlock
x := p.oe.index(node) x := p.oe.index(node)
// Step 14.1. // Steps 13.1-13.2
j := 0 for j := 0; j < 3; j++ {
for { // Step 13.3.
// Step 14.2.
j++
// Step. 14.3.
x-- x--
node = p.oe[x] node = p.oe[x]
// Step 14.4. Go to the next step if node is formatting element. // Step 13.4 - 13.5.
if node == formattingElement {
break
}
// Step 14.5. Remove node from the list of active formatting elements if
// inner loop counter is greater than three and node is in the list of
// active formatting elements.
if ni := p.afe.index(node); j > 3 && ni > -1 {
p.afe.remove(node)
// If any element of the list of active formatting elements is removed,
// we need to take care whether bookmark should be decremented or not.
// This is because the value of bookmark may exceed the size of the
// list by removing elements from the list.
if ni <= bookmark {
bookmark--
}
continue
}
// Step 14.6. Continue the next inner loop if node is not in the list of
// active formatting elements.
if p.afe.index(node) == -1 { if p.afe.index(node) == -1 {
p.oe.remove(node) p.oe.remove(node)
continue continue
} }
// Step 14.7. // Step 13.6.
if node == formattingElement {
break
}
// Step 13.7.
clone := node.clone() clone := node.clone()
p.afe[p.afe.index(node)] = clone p.afe[p.afe.index(node)] = clone
p.oe[p.oe.index(node)] = clone p.oe[p.oe.index(node)] = clone
node = clone node = clone
// Step 14.8. // Step 13.8.
if lastNode == furthestBlock { if lastNode == furthestBlock {
bookmark = p.afe.index(node) + 1 bookmark = p.afe.index(node) + 1
} }
// Step 14.9. // Step 13.9.
if lastNode.Parent != nil { if lastNode.Parent != nil {
lastNode.Parent.RemoveChild(lastNode) lastNode.Parent.RemoveChild(lastNode)
} }
node.AppendChild(lastNode) node.AppendChild(lastNode)
// Step 14.10. // Step 13.10.
lastNode = node lastNode = node
} }
// Step 15. Reparent lastNode to the common ancestor, // Step 14. Reparent lastNode to the common ancestor,
// or for misnested table nodes, to the foster parent. // or for misnested table nodes, to the foster parent.
if lastNode.Parent != nil { if lastNode.Parent != nil {
lastNode.Parent.RemoveChild(lastNode) lastNode.Parent.RemoveChild(lastNode)
@ -1316,13 +1317,13 @@ func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom, tagName string) {
commonAncestor.AppendChild(lastNode) commonAncestor.AppendChild(lastNode)
} }
// Steps 16-18. Reparent nodes from the furthest block's children // Steps 15-17. Reparent nodes from the furthest block's children
// to a clone of the formatting element. // to a clone of the formatting element.
clone := formattingElement.clone() clone := formattingElement.clone()
reparentChildren(clone, furthestBlock) reparentChildren(clone, furthestBlock)
furthestBlock.AppendChild(clone) furthestBlock.AppendChild(clone)
// Step 19. Fix up the list of active formatting elements. // Step 18. Fix up the list of active formatting elements.
if oldLoc := p.afe.index(formattingElement); oldLoc != -1 && oldLoc < bookmark { if oldLoc := p.afe.index(formattingElement); oldLoc != -1 && oldLoc < bookmark {
// Move the bookmark with the rest of the list. // Move the bookmark with the rest of the list.
bookmark-- bookmark--
@ -1330,7 +1331,7 @@ func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom, tagName string) {
p.afe.remove(formattingElement) p.afe.remove(formattingElement)
p.afe.insert(bookmark, clone) p.afe.insert(bookmark, clone)
// Step 20. Fix up the stack of open elements. // Step 19. Fix up the stack of open elements.
p.oe.remove(formattingElement) p.oe.remove(formattingElement)
p.oe.insert(p.oe.index(furthestBlock)+1, clone) p.oe.insert(p.oe.index(furthestBlock)+1, clone)
} }
@ -1501,13 +1502,14 @@ func inCaptionIM(p *parser) bool {
case StartTagToken: case StartTagToken:
switch p.tok.DataAtom { switch p.tok.DataAtom {
case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Td, a.Tfoot, a.Thead, a.Tr: case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Td, a.Tfoot, a.Thead, a.Tr:
if !p.popUntil(tableScope, a.Caption) { if p.popUntil(tableScope, a.Caption) {
p.clearActiveFormattingElements()
p.im = inTableIM
return false
} else {
// Ignore the token. // Ignore the token.
return true return true
} }
p.clearActiveFormattingElements()
p.im = inTableIM
return false
case a.Select: case a.Select:
p.reconstructActiveFormattingElements() p.reconstructActiveFormattingElements()
p.addElement() p.addElement()
@ -1524,13 +1526,14 @@ func inCaptionIM(p *parser) bool {
} }
return true return true
case a.Table: case a.Table:
if !p.popUntil(tableScope, a.Caption) { if p.popUntil(tableScope, a.Caption) {
p.clearActiveFormattingElements()
p.im = inTableIM
return false
} else {
// Ignore the token. // Ignore the token.
return true return true
} }
p.clearActiveFormattingElements()
p.im = inTableIM
return false
case a.Body, a.Col, a.Colgroup, a.Html, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr: case a.Body, a.Col, a.Colgroup, a.Html, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
// Ignore the token. // Ignore the token.
return true return true
@ -1774,11 +1777,12 @@ func inSelectIM(p *parser) bool {
} }
p.addElement() p.addElement()
case a.Select: case a.Select:
if !p.popUntil(selectScope, a.Select) { if p.popUntil(selectScope, a.Select) {
p.resetInsertionMode()
} else {
// Ignore the token. // Ignore the token.
return true return true
} }
p.resetInsertionMode()
case a.Input, a.Keygen, a.Textarea: case a.Input, a.Keygen, a.Textarea:
if p.elementInScope(selectScope, a.Select) { if p.elementInScope(selectScope, a.Select) {
p.parseImpliedToken(EndTagToken, a.Select, a.Select.String()) p.parseImpliedToken(EndTagToken, a.Select, a.Select.String())
@ -1806,11 +1810,12 @@ func inSelectIM(p *parser) bool {
p.oe = p.oe[:i] p.oe = p.oe[:i]
} }
case a.Select: case a.Select:
if !p.popUntil(selectScope, a.Select) { if p.popUntil(selectScope, a.Select) {
p.resetInsertionMode()
} else {
// Ignore the token. // Ignore the token.
return true return true
} }
p.resetInsertionMode()
case a.Template: case a.Template:
return inHeadIM(p) return inHeadIM(p)
} }
@ -2131,31 +2136,28 @@ func parseForeignContent(p *parser) bool {
Data: p.tok.Data, Data: p.tok.Data,
}) })
case StartTagToken: case StartTagToken:
if !p.fragment { b := breakout[p.tok.Data]
b := breakout[p.tok.Data] if p.tok.DataAtom == a.Font {
if p.tok.DataAtom == a.Font { loop:
loop: for _, attr := range p.tok.Attr {
for _, attr := range p.tok.Attr { switch attr.Key {
switch attr.Key { case "color", "face", "size":
case "color", "face", "size": b = true
b = true break loop
break loop
}
} }
} }
if b {
for i := len(p.oe) - 1; i >= 0; i-- {
n := p.oe[i]
if n.Namespace == "" || htmlIntegrationPoint(n) || mathMLTextIntegrationPoint(n) {
p.oe = p.oe[:i+1]
break
}
}
return false
}
} }
current := p.adjustedCurrentNode() if b {
switch current.Namespace { for i := len(p.oe) - 1; i >= 0; i-- {
n := p.oe[i]
if n.Namespace == "" || htmlIntegrationPoint(n) || mathMLTextIntegrationPoint(n) {
p.oe = p.oe[:i+1]
break
}
}
return false
}
switch p.top().Namespace {
case "math": case "math":
adjustAttributeNames(p.tok.Attr, mathMLAttributeAdjustments) adjustAttributeNames(p.tok.Attr, mathMLAttributeAdjustments)
case "svg": case "svg":
@ -2170,7 +2172,7 @@ func parseForeignContent(p *parser) bool {
panic("html: bad parser state: unexpected namespace") panic("html: bad parser state: unexpected namespace")
} }
adjustForeignAttributes(p.tok.Attr) adjustForeignAttributes(p.tok.Attr)
namespace := current.Namespace namespace := p.top().Namespace
p.addElement() p.addElement()
p.top().Namespace = namespace p.top().Namespace = namespace
if namespace != "" { if namespace != "" {
@ -2199,20 +2201,12 @@ func parseForeignContent(p *parser) bool {
return true return true
} }
// Section 12.2.4.2.
func (p *parser) adjustedCurrentNode() *Node {
if len(p.oe) == 1 && p.fragment && p.context != nil {
return p.context
}
return p.oe.top()
}
// Section 12.2.6. // Section 12.2.6.
func (p *parser) inForeignContent() bool { func (p *parser) inForeignContent() bool {
if len(p.oe) == 0 { if len(p.oe) == 0 {
return false return false
} }
n := p.adjustedCurrentNode() n := p.oe[len(p.oe)-1]
if n.Namespace == "" { if n.Namespace == "" {
return false return false
} }
@ -2347,7 +2341,8 @@ func ParseWithOptions(r io.Reader, opts ...ParseOption) (*Node, error) {
f(p) f(p)
} }
if err := p.parse(); err != nil { err := p.parse()
if err != nil {
return nil, err return nil, err
} }
return p.doc, nil return p.doc, nil
@ -2369,6 +2364,7 @@ func ParseFragmentWithOptions(r io.Reader, context *Node, opts ...ParseOption) (
contextTag = context.DataAtom.String() contextTag = context.DataAtom.String()
} }
p := &parser{ p := &parser{
tokenizer: NewTokenizerFragment(r, contextTag),
doc: &Node{ doc: &Node{
Type: DocumentNode, Type: DocumentNode,
}, },
@ -2376,11 +2372,6 @@ func ParseFragmentWithOptions(r io.Reader, context *Node, opts ...ParseOption) (
fragment: true, fragment: true,
context: context, context: context,
} }
if context != nil && context.Namespace != "" {
p.tokenizer = NewTokenizer(r)
} else {
p.tokenizer = NewTokenizerFragment(r, contextTag)
}
for _, f := range opts { for _, f := range opts {
f(p) f(p)
@ -2405,7 +2396,8 @@ func ParseFragmentWithOptions(r io.Reader, context *Node, opts ...ParseOption) (
} }
} }
if err := p.parse(); err != nil { err := p.parse()
if err != nil {
return nil, err return nil, err
} }

View File

@ -134,9 +134,6 @@ func render1(w writer, n *Node) error {
} }
} }
return w.WriteByte('>') return w.WriteByte('>')
case RawNode:
_, err := w.WriteString(n.Data)
return err
default: default:
return errors.New("html: unknown node type") return errors.New("html: unknown node type")
} }
@ -255,19 +252,20 @@ func writeQuoted(w writer, s string) error {
// Section 12.1.2, "Elements", gives this list of void elements. Void elements // Section 12.1.2, "Elements", gives this list of void elements. Void elements
// are those that can't have any contents. // are those that can't have any contents.
var voidElements = map[string]bool{ var voidElements = map[string]bool{
"area": true, "area": true,
"base": true, "base": true,
"br": true, "br": true,
"col": true, "col": true,
"embed": true, "command": true,
"hr": true, "embed": true,
"img": true, "hr": true,
"input": true, "img": true,
"keygen": true, "input": true,
"link": true, "keygen": true,
"meta": true, "link": true,
"param": true, "meta": true,
"source": true, "param": true,
"track": true, "source": true,
"wbr": true, "track": true,
"wbr": true,
} }

View File

@ -296,7 +296,8 @@ func (z *Tokenizer) Buffered() []byte {
// too many times in succession. // too many times in succession.
func readAtLeastOneByte(r io.Reader, b []byte) (int, error) { func readAtLeastOneByte(r io.Reader, b []byte) (int, error) {
for i := 0; i < 100; i++ { for i := 0; i < 100; i++ {
if n, err := r.Read(b); n != 0 || err != nil { n, err := r.Read(b)
if n != 0 || err != nil {
return n, err return n, err
} }
} }
@ -346,7 +347,6 @@ loop:
break loop break loop
} }
if c != '/' { if c != '/' {
z.raw.end--
continue loop continue loop
} }
if z.readRawEndTag() || z.err != nil { if z.readRawEndTag() || z.err != nil {
@ -1067,11 +1067,6 @@ loop:
// Raw returns the unmodified text of the current token. Calling Next, Token, // Raw returns the unmodified text of the current token. Calling Next, Token,
// Text, TagName or TagAttr may change the contents of the returned slice. // Text, TagName or TagAttr may change the contents of the returned slice.
//
// The token stream's raw bytes partition the byte stream (up until an
// ErrorToken). There are no overlaps or gaps between two consecutive token's
// raw bytes. One implication is that the byte offset of the current token is
// the sum of the lengths of all previous tokens' raw bytes.
func (z *Tokenizer) Raw() []byte { func (z *Tokenizer) Raw() []byte {
return z.buf[z.raw.start:z.raw.end] return z.buf[z.raw.start:z.raw.end]
} }

View File

@ -107,7 +107,6 @@ func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMis
// dialCall is an in-flight Transport dial call to a host. // dialCall is an in-flight Transport dial call to a host.
type dialCall struct { type dialCall struct {
_ incomparable
p *clientConnPool p *clientConnPool
done chan struct{} // closed when done done chan struct{} // closed when done
res *ClientConn // valid after done is closed res *ClientConn // valid after done is closed
@ -181,7 +180,6 @@ func (p *clientConnPool) addConnIfNeeded(key string, t *Transport, c *tls.Conn)
} }
type addConnCall struct { type addConnCall struct {
_ incomparable
p *clientConnPool p *clientConnPool
done chan struct{} // closed when done done chan struct{} // closed when done
err error err error
@ -202,6 +200,12 @@ func (c *addConnCall) run(t *Transport, key string, tc *tls.Conn) {
close(c.done) close(c.done)
} }
func (p *clientConnPool) addConn(key string, cc *ClientConn) {
p.mu.Lock()
p.addConnLocked(key, cc)
p.mu.Unlock()
}
// p.mu must be held // p.mu must be held
func (p *clientConnPool) addConnLocked(key string, cc *ClientConn) { func (p *clientConnPool) addConnLocked(key string, cc *ClientConn) {
for _, v := range p.conns[key] { for _, v := range p.conns[key] {

View File

@ -8,8 +8,6 @@ package http2
// flow is the flow control window's size. // flow is the flow control window's size.
type flow struct { type flow struct {
_ incomparable
// n is the number of DATA bytes we're allowed to send. // n is the number of DATA bytes we're allowed to send.
// A flow is kept both on a conn and a per-stream. // A flow is kept both on a conn and a per-stream.
n int32 n int32

View File

@ -150,7 +150,7 @@ func appendIndexed(dst []byte, i uint64) []byte {
// extended buffer. // extended buffer.
// //
// If f.Sensitive is true, "Never Indexed" representation is used. If // If f.Sensitive is true, "Never Indexed" representation is used. If
// f.Sensitive is false and indexing is true, "Incremental Indexing" // f.Sensitive is false and indexing is true, "Inremental Indexing"
// representation is used. // representation is used.
func appendNewName(dst []byte, f HeaderField, indexing bool) []byte { func appendNewName(dst []byte, f HeaderField, indexing bool) []byte {
dst = append(dst, encodeTypeByte(indexing, f.Sensitive)) dst = append(dst, encodeTypeByte(indexing, f.Sensitive))

View File

@ -105,14 +105,7 @@ func huffmanDecode(buf *bytes.Buffer, maxLen int, v []byte) error {
return nil return nil
} }
// incomparable is a zero-width, non-comparable type. Adding it to a struct
// makes that struct also non-comparable, and generally doesn't add
// any size (as long as it's first).
type incomparable [0]func()
type node struct { type node struct {
_ incomparable
// children is non-nil for internal nodes // children is non-nil for internal nodes
children *[256]*node children *[256]*node

View File

@ -19,6 +19,7 @@ package http2 // import "golang.org/x/net/http2"
import ( import (
"bufio" "bufio"
"crypto/tls" "crypto/tls"
"errors"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
@ -172,6 +173,11 @@ func (s SettingID) String() string {
return fmt.Sprintf("UNKNOWN_SETTING_%d", uint16(s)) return fmt.Sprintf("UNKNOWN_SETTING_%d", uint16(s))
} }
var (
errInvalidHeaderFieldName = errors.New("http2: invalid header field name")
errInvalidHeaderFieldValue = errors.New("http2: invalid header field value")
)
// validWireHeaderFieldName reports whether v is a valid header field // validWireHeaderFieldName reports whether v is a valid header field
// name (key). See httpguts.ValidHeaderName for the base rules. // name (key). See httpguts.ValidHeaderName for the base rules.
// //
@ -241,7 +247,6 @@ func (cw closeWaiter) Wait() {
// Its buffered writer is lazily allocated as needed, to minimize // Its buffered writer is lazily allocated as needed, to minimize
// idle memory usage with many connections. // idle memory usage with many connections.
type bufferedWriter struct { type bufferedWriter struct {
_ incomparable
w io.Writer // immutable w io.Writer // immutable
bw *bufio.Writer // non-nil when data is buffered bw *bufio.Writer // non-nil when data is buffered
} }
@ -314,7 +319,6 @@ func bodyAllowedForStatus(status int) bool {
} }
type httpError struct { type httpError struct {
_ incomparable
msg string msg string
timeout bool timeout bool
} }
@ -378,8 +382,3 @@ func (s *sorter) SortStrings(ss []string) {
func validPseudoPath(v string) bool { func validPseudoPath(v string) bool {
return (len(v) > 0 && v[0] == '/') || v == "*" return (len(v) > 0 && v[0] == '/') || v == "*"
} }
// incomparable is a zero-width, non-comparable type. Adding it to a struct
// makes that struct also non-comparable, and generally doesn't add
// any size (as long as it's first).
type incomparable [0]func()

View File

@ -17,7 +17,6 @@ type pipe struct {
mu sync.Mutex mu sync.Mutex
c sync.Cond // c.L lazily initialized to &p.mu c sync.Cond // c.L lazily initialized to &p.mu
b pipeBuffer // nil when done reading b pipeBuffer // nil when done reading
unread int // bytes unread when done
err error // read error once empty. non-nil means closed. err error // read error once empty. non-nil means closed.
breakErr error // immediate read error (caller doesn't see rest of b) breakErr error // immediate read error (caller doesn't see rest of b)
donec chan struct{} // closed on error donec chan struct{} // closed on error
@ -34,7 +33,7 @@ func (p *pipe) Len() int {
p.mu.Lock() p.mu.Lock()
defer p.mu.Unlock() defer p.mu.Unlock()
if p.b == nil { if p.b == nil {
return p.unread return 0
} }
return p.b.Len() return p.b.Len()
} }
@ -81,7 +80,6 @@ func (p *pipe) Write(d []byte) (n int, err error) {
return 0, errClosedPipeWrite return 0, errClosedPipeWrite
} }
if p.breakErr != nil { if p.breakErr != nil {
p.unread += len(d)
return len(d), nil // discard when there is no reader return len(d), nil // discard when there is no reader
} }
return p.b.Write(d) return p.b.Write(d)
@ -119,9 +117,6 @@ func (p *pipe) closeWithError(dst *error, err error, fn func()) {
} }
p.readFn = fn p.readFn = fn
if dst == &p.breakErr { if dst == &p.breakErr {
if p.b != nil {
p.unread += p.b.Len()
}
p.b = nil p.b = nil
} }
*dst = err *dst = err

View File

@ -252,7 +252,7 @@ func ConfigureServer(s *http.Server, conf *Server) error {
} }
} }
if !haveRequired { if !haveRequired {
return fmt.Errorf("http2: TLSConfig.CipherSuites is missing an HTTP/2-required AES_128_GCM_SHA256 cipher (need at least one of TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 or TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256).") return fmt.Errorf("http2: TLSConfig.CipherSuites is missing an HTTP/2-required AES_128_GCM_SHA256 cipher.")
} }
} }
@ -322,7 +322,7 @@ type ServeConnOpts struct {
} }
func (o *ServeConnOpts) context() context.Context { func (o *ServeConnOpts) context() context.Context {
if o != nil && o.Context != nil { if o.Context != nil {
return o.Context return o.Context
} }
return context.Background() return context.Background()
@ -581,10 +581,13 @@ type stream struct {
cancelCtx func() cancelCtx func()
// owned by serverConn's serve loop: // owned by serverConn's serve loop:
bodyBytes int64 // body bytes seen so far bodyBytes int64 // body bytes seen so far
declBodyBytes int64 // or -1 if undeclared declBodyBytes int64 // or -1 if undeclared
flow flow // limits writing from Handler to client flow flow // limits writing from Handler to client
inflow flow // what the client is allowed to POST/etc to us inflow flow // what the client is allowed to POST/etc to us
parent *stream // or nil
numTrailerValues int64
weight uint8
state streamState state streamState
resetQueued bool // RST_STREAM queued for write; set by sc.resetStream resetQueued bool // RST_STREAM queued for write; set by sc.resetStream
gotTrailerHeader bool // HEADER frame for trailers was seen gotTrailerHeader bool // HEADER frame for trailers was seen
@ -761,7 +764,6 @@ func (sc *serverConn) readFrames() {
// frameWriteResult is the message passed from writeFrameAsync to the serve goroutine. // frameWriteResult is the message passed from writeFrameAsync to the serve goroutine.
type frameWriteResult struct { type frameWriteResult struct {
_ incomparable
wr FrameWriteRequest // what was written (or attempted) wr FrameWriteRequest // what was written (or attempted)
err error // result of the writeFrame call err error // result of the writeFrame call
} }
@ -772,7 +774,7 @@ type frameWriteResult struct {
// serverConn. // serverConn.
func (sc *serverConn) writeFrameAsync(wr FrameWriteRequest) { func (sc *serverConn) writeFrameAsync(wr FrameWriteRequest) {
err := wr.write.writeFrame(sc) err := wr.write.writeFrame(sc)
sc.wroteFrameCh <- frameWriteResult{wr: wr, err: err} sc.wroteFrameCh <- frameWriteResult{wr, err}
} }
func (sc *serverConn) closeAllStreamsOnConnClose() { func (sc *serverConn) closeAllStreamsOnConnClose() {
@ -1162,7 +1164,7 @@ func (sc *serverConn) startFrameWrite(wr FrameWriteRequest) {
if wr.write.staysWithinBuffer(sc.bw.Available()) { if wr.write.staysWithinBuffer(sc.bw.Available()) {
sc.writingFrameAsync = false sc.writingFrameAsync = false
err := wr.write.writeFrame(sc) err := wr.write.writeFrame(sc)
sc.wroteFrame(frameWriteResult{wr: wr, err: err}) sc.wroteFrame(frameWriteResult{wr, err})
} else { } else {
sc.writingFrameAsync = true sc.writingFrameAsync = true
go sc.writeFrameAsync(wr) go sc.writeFrameAsync(wr)
@ -2058,7 +2060,7 @@ func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*r
var trailer http.Header var trailer http.Header
for _, v := range rp.header["Trailer"] { for _, v := range rp.header["Trailer"] {
for _, key := range strings.Split(v, ",") { for _, key := range strings.Split(v, ",") {
key = http.CanonicalHeaderKey(textproto.TrimString(key)) key = http.CanonicalHeaderKey(strings.TrimSpace(key))
switch key { switch key {
case "Transfer-Encoding", "Trailer", "Content-Length": case "Transfer-Encoding", "Trailer", "Content-Length":
// Bogus. (copy of http1 rules) // Bogus. (copy of http1 rules)
@ -2276,7 +2278,6 @@ func (sc *serverConn) sendWindowUpdate32(st *stream, n int32) {
// requestBody is the Handler's Request.Body type. // requestBody is the Handler's Request.Body type.
// Read and Close may be called concurrently. // Read and Close may be called concurrently.
type requestBody struct { type requestBody struct {
_ incomparable
stream *stream stream *stream
conn *serverConn conn *serverConn
closed bool // for use by Close only closed bool // for use by Close only
@ -2414,11 +2415,7 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
clen = strconv.Itoa(len(p)) clen = strconv.Itoa(len(p))
} }
_, hasContentType := rws.snapHeader["Content-Type"] _, hasContentType := rws.snapHeader["Content-Type"]
// If the Content-Encoding is non-blank, we shouldn't if !hasContentType && bodyAllowedForStatus(rws.status) && len(p) > 0 {
// sniff the body. See Issue golang.org/issue/31753.
ce := rws.snapHeader.Get("Content-Encoding")
hasCE := len(ce) > 0
if !hasCE && !hasContentType && bodyAllowedForStatus(rws.status) && len(p) > 0 {
ctype = http.DetectContentType(p) ctype = http.DetectContentType(p)
} }
var date string var date string
@ -2527,7 +2524,7 @@ const TrailerPrefix = "Trailer:"
// trailers. That worked for a while, until we found the first major // trailers. That worked for a while, until we found the first major
// user of Trailers in the wild: gRPC (using them only over http2), // user of Trailers in the wild: gRPC (using them only over http2),
// and gRPC libraries permit setting trailers mid-stream without // and gRPC libraries permit setting trailers mid-stream without
// predeclaring them. So: change of plans. We still permit the old // predeclarnig them. So: change of plans. We still permit the old
// way, but we also permit this hack: if a Header() key begins with // way, but we also permit this hack: if a Header() key begins with
// "Trailer:", the suffix of that key is a Trailer. Because ':' is an // "Trailer:", the suffix of that key is a Trailer. Because ':' is an
// invalid token byte anyway, there is no ambiguity. (And it's already // invalid token byte anyway, there is no ambiguity. (And it's already
@ -2827,7 +2824,7 @@ func (sc *serverConn) startPush(msg *startPushRequest) {
// PUSH_PROMISE frames MUST only be sent on a peer-initiated stream that // PUSH_PROMISE frames MUST only be sent on a peer-initiated stream that
// is in either the "open" or "half-closed (remote)" state. // is in either the "open" or "half-closed (remote)" state.
if msg.parent.state != stateOpen && msg.parent.state != stateHalfClosedRemote { if msg.parent.state != stateOpen && msg.parent.state != stateHalfClosedRemote {
// responseWriter.Push checks that the stream is peer-initiated. // responseWriter.Push checks that the stream is peer-initiaed.
msg.done <- errStreamClosed msg.done <- errStreamClosed
return return
} }

View File

@ -93,7 +93,7 @@ type Transport struct {
// send in the initial settings frame. It is how many bytes // send in the initial settings frame. It is how many bytes
// of response headers are allowed. Unlike the http2 spec, zero here // of response headers are allowed. Unlike the http2 spec, zero here
// means to use a default limit (currently 10MB). If you actually // means to use a default limit (currently 10MB). If you actually
// want to advertise an unlimited value to the peer, Transport // want to advertise an ulimited value to the peer, Transport
// interprets the highest possible value here (0xffffffff or 1<<32-1) // interprets the highest possible value here (0xffffffff or 1<<32-1)
// to mean no limit. // to mean no limit.
MaxHeaderListSize uint32 MaxHeaderListSize uint32
@ -108,19 +108,6 @@ type Transport struct {
// waiting for their turn. // waiting for their turn.
StrictMaxConcurrentStreams bool StrictMaxConcurrentStreams bool
// ReadIdleTimeout is the timeout after which a health check using ping
// frame will be carried out if no frame is received on the connection.
// Note that a ping response will is considered a received frame, so if
// there is no other traffic on the connection, the health check will
// be performed every ReadIdleTimeout interval.
// If zero, no health check is performed.
ReadIdleTimeout time.Duration
// PingTimeout is the timeout after which the connection will be closed
// if a response to Ping is not received.
// Defaults to 15s.
PingTimeout time.Duration
// t1, if non-nil, is the standard library Transport using // t1, if non-nil, is the standard library Transport using
// this transport. Its settings are used (but not its // this transport. Its settings are used (but not its
// RoundTrip method, etc). // RoundTrip method, etc).
@ -144,14 +131,6 @@ func (t *Transport) disableCompression() bool {
return t.DisableCompression || (t.t1 != nil && t.t1.DisableCompression) return t.DisableCompression || (t.t1 != nil && t.t1.DisableCompression)
} }
func (t *Transport) pingTimeout() time.Duration {
if t.PingTimeout == 0 {
return 15 * time.Second
}
return t.PingTimeout
}
// ConfigureTransport configures a net/http HTTP/1 Transport to use HTTP/2. // ConfigureTransport configures a net/http HTTP/1 Transport to use HTTP/2.
// It returns an error if t1 has already been HTTP/2-enabled. // It returns an error if t1 has already been HTTP/2-enabled.
func ConfigureTransport(t1 *http.Transport) error { func ConfigureTransport(t1 *http.Transport) error {
@ -248,7 +227,6 @@ type ClientConn struct {
br *bufio.Reader br *bufio.Reader
fr *Framer fr *Framer
lastActive time.Time lastActive time.Time
lastIdle time.Time // time last idle
// Settings from peer: (also guarded by mu) // Settings from peer: (also guarded by mu)
maxFrameSize uint32 maxFrameSize uint32
maxConcurrentStreams uint32 maxConcurrentStreams uint32
@ -625,7 +603,7 @@ func (t *Transport) expectContinueTimeout() time.Duration {
} }
func (t *Transport) NewClientConn(c net.Conn) (*ClientConn, error) { func (t *Transport) NewClientConn(c net.Conn) (*ClientConn, error) {
return t.newClientConn(c, t.disableKeepAlives()) return t.newClientConn(c, false)
} }
func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, error) { func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, error) {
@ -696,20 +674,6 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, erro
return cc, nil return cc, nil
} }
func (cc *ClientConn) healthCheck() {
pingTimeout := cc.t.pingTimeout()
// We don't need to periodically ping in the health check, because the readLoop of ClientConn will
// trigger the healthCheck again if there is no frame received.
ctx, cancel := context.WithTimeout(context.Background(), pingTimeout)
defer cancel()
err := cc.Ping(ctx)
if err != nil {
cc.closeForLostPing()
cc.t.connPool().MarkDead(cc)
return
}
}
func (cc *ClientConn) setGoAway(f *GoAwayFrame) { func (cc *ClientConn) setGoAway(f *GoAwayFrame) {
cc.mu.Lock() cc.mu.Lock()
defer cc.mu.Unlock() defer cc.mu.Unlock()
@ -772,8 +736,7 @@ func (cc *ClientConn) idleStateLocked() (st clientConnIdleState) {
} }
st.canTakeNewRequest = cc.goAway == nil && !cc.closed && !cc.closing && maxConcurrentOkay && st.canTakeNewRequest = cc.goAway == nil && !cc.closed && !cc.closing && maxConcurrentOkay &&
int64(cc.nextStreamID)+2*int64(cc.pendingRequests) < math.MaxInt32 && int64(cc.nextStreamID)+2*int64(cc.pendingRequests) < math.MaxInt32
!cc.tooIdleLocked()
st.freshConn = cc.nextStreamID == 1 && st.canTakeNewRequest st.freshConn = cc.nextStreamID == 1 && st.canTakeNewRequest
return return
} }
@ -783,16 +746,6 @@ func (cc *ClientConn) canTakeNewRequestLocked() bool {
return st.canTakeNewRequest return st.canTakeNewRequest
} }
// tooIdleLocked reports whether this connection has been been sitting idle
// for too much wall time.
func (cc *ClientConn) tooIdleLocked() bool {
// The Round(0) strips the monontonic clock reading so the
// times are compared based on their wall time. We don't want
// to reuse a connection that's been sitting idle during
// VM/laptop suspend if monotonic time was also frozen.
return cc.idleTimeout != 0 && !cc.lastIdle.IsZero() && time.Since(cc.lastIdle.Round(0)) > cc.idleTimeout
}
// onIdleTimeout is called from a time.AfterFunc goroutine. It will // onIdleTimeout is called from a time.AfterFunc goroutine. It will
// only be called when we're idle, but because we're coming from a new // only be called when we're idle, but because we're coming from a new
// goroutine, there could be a new request coming in at the same time, // goroutine, there could be a new request coming in at the same time,
@ -881,12 +834,14 @@ func (cc *ClientConn) sendGoAway() error {
return nil return nil
} }
// closes the client connection immediately. In-flight requests are interrupted. // Close closes the client connection immediately.
// err is sent to streams. //
func (cc *ClientConn) closeForError(err error) error { // In-flight requests are interrupted. For a graceful shutdown, use Shutdown instead.
func (cc *ClientConn) Close() error {
cc.mu.Lock() cc.mu.Lock()
defer cc.cond.Broadcast() defer cc.cond.Broadcast()
defer cc.mu.Unlock() defer cc.mu.Unlock()
err := errors.New("http2: client connection force closed via ClientConn.Close")
for id, cs := range cc.streams { for id, cs := range cc.streams {
select { select {
case cs.resc <- resAndError{err: err}: case cs.resc <- resAndError{err: err}:
@ -899,20 +854,6 @@ func (cc *ClientConn) closeForError(err error) error {
return cc.tconn.Close() return cc.tconn.Close()
} }
// Close closes the client connection immediately.
//
// In-flight requests are interrupted. For a graceful shutdown, use Shutdown instead.
func (cc *ClientConn) Close() error {
err := errors.New("http2: client connection force closed via ClientConn.Close")
return cc.closeForError(err)
}
// closes the client connection immediately. In-flight requests are interrupted.
func (cc *ClientConn) closeForLostPing() error {
err := errors.New("http2: client connection lost")
return cc.closeForError(err)
}
const maxAllocFrameSize = 512 << 10 const maxAllocFrameSize = 512 << 10
// frameBuffer returns a scratch buffer suitable for writing DATA frames. // frameBuffer returns a scratch buffer suitable for writing DATA frames.
@ -963,7 +904,7 @@ func commaSeparatedTrailers(req *http.Request) (string, error) {
k = http.CanonicalHeaderKey(k) k = http.CanonicalHeaderKey(k)
switch k { switch k {
case "Transfer-Encoding", "Trailer", "Content-Length": case "Transfer-Encoding", "Trailer", "Content-Length":
return "", fmt.Errorf("invalid Trailer key %q", k) return "", &badStringError{"invalid Trailer key", k}
} }
keys = append(keys, k) keys = append(keys, k)
} }
@ -1209,7 +1150,6 @@ func (cc *ClientConn) awaitOpenSlotForRequest(req *http.Request) error {
} }
return errClientConnUnusable return errClientConnUnusable
} }
cc.lastIdle = time.Time{}
if int64(len(cc.streams))+1 <= int64(cc.maxConcurrentStreams) { if int64(len(cc.streams))+1 <= int64(cc.maxConcurrentStreams) {
if waitingForConn != nil { if waitingForConn != nil {
close(waitingForConn) close(waitingForConn)
@ -1276,8 +1216,6 @@ var (
// abort request body write, but send stream reset of cancel. // abort request body write, but send stream reset of cancel.
errStopReqBodyWriteAndCancel = errors.New("http2: canceling request") errStopReqBodyWriteAndCancel = errors.New("http2: canceling request")
errReqBodyTooLong = errors.New("http2: request body larger than specified content length")
) )
func (cs *clientStream) writeRequestBody(body io.Reader, bodyCloser io.Closer) (err error) { func (cs *clientStream) writeRequestBody(body io.Reader, bodyCloser io.Closer) (err error) {
@ -1300,32 +1238,10 @@ func (cs *clientStream) writeRequestBody(body io.Reader, bodyCloser io.Closer) (
req := cs.req req := cs.req
hasTrailers := req.Trailer != nil hasTrailers := req.Trailer != nil
remainLen := actualContentLength(req)
hasContentLen := remainLen != -1
var sawEOF bool var sawEOF bool
for !sawEOF { for !sawEOF {
n, err := body.Read(buf[:len(buf)-1]) n, err := body.Read(buf)
if hasContentLen {
remainLen -= int64(n)
if remainLen == 0 && err == nil {
// The request body's Content-Length was predeclared and
// we just finished reading it all, but the underlying io.Reader
// returned the final chunk with a nil error (which is one of
// the two valid things a Reader can do at EOF). Because we'd prefer
// to send the END_STREAM bit early, double-check that we're actually
// at EOF. Subsequent reads should return (0, EOF) at this point.
// If either value is different, we return an error in one of two ways below.
var n1 int
n1, err = body.Read(buf[n:])
remainLen -= int64(n1)
}
if remainLen < 0 {
err = errReqBodyTooLong
cc.writeStreamReset(cs.ID, ErrCodeCancel, err)
return err
}
}
if err == io.EOF { if err == io.EOF {
sawEOF = true sawEOF = true
err = nil err = nil
@ -1441,6 +1357,13 @@ func (cs *clientStream) awaitFlowControl(maxBytes int) (taken int32, err error)
} }
} }
type badStringError struct {
what string
str string
}
func (e *badStringError) Error() string { return fmt.Sprintf("%s %q", e.what, e.str) }
// requires cc.mu be held. // requires cc.mu be held.
func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trailers string, contentLength int64) ([]byte, error) { func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trailers string, contentLength int64) ([]byte, error) {
cc.hbuf.Reset() cc.hbuf.Reset()
@ -1531,29 +1454,7 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
if vv[0] == "" { if vv[0] == "" {
continue continue
} }
} else if strings.EqualFold(k, "cookie") {
// Per 8.1.2.5 To allow for better compression efficiency, the
// Cookie header field MAY be split into separate header fields,
// each with one or more cookie-pairs.
for _, v := range vv {
for {
p := strings.IndexByte(v, ';')
if p < 0 {
break
}
f("cookie", v[:p])
p++
// strip space after semicolon if any.
for p+1 <= len(v) && v[p] == ' ' {
p++
}
v = v[p:]
}
if len(v) > 0 {
f("cookie", v)
}
}
continue
} }
for _, v := range vv { for _, v := range vv {
@ -1656,7 +1557,6 @@ func (cc *ClientConn) writeHeader(name, value string) {
} }
type resAndError struct { type resAndError struct {
_ incomparable
res *http.Response res *http.Response
err error err error
} }
@ -1692,7 +1592,6 @@ func (cc *ClientConn) streamByID(id uint32, andRemove bool) *clientStream {
delete(cc.streams, id) delete(cc.streams, id)
if len(cc.streams) == 0 && cc.idleTimer != nil { if len(cc.streams) == 0 && cc.idleTimer != nil {
cc.idleTimer.Reset(cc.idleTimeout) cc.idleTimer.Reset(cc.idleTimeout)
cc.lastIdle = time.Now()
} }
close(cs.done) close(cs.done)
// Wake up checkResetOrDone via clientStream.awaitFlowControl and // Wake up checkResetOrDone via clientStream.awaitFlowControl and
@ -1704,7 +1603,6 @@ func (cc *ClientConn) streamByID(id uint32, andRemove bool) *clientStream {
// clientConnReadLoop is the state owned by the clientConn's frame-reading readLoop. // clientConnReadLoop is the state owned by the clientConn's frame-reading readLoop.
type clientConnReadLoop struct { type clientConnReadLoop struct {
_ incomparable
cc *ClientConn cc *ClientConn
closeWhenIdle bool closeWhenIdle bool
} }
@ -1784,17 +1682,8 @@ func (rl *clientConnReadLoop) run() error {
rl.closeWhenIdle = cc.t.disableKeepAlives() || cc.singleUse rl.closeWhenIdle = cc.t.disableKeepAlives() || cc.singleUse
gotReply := false // ever saw a HEADERS reply gotReply := false // ever saw a HEADERS reply
gotSettings := false gotSettings := false
readIdleTimeout := cc.t.ReadIdleTimeout
var t *time.Timer
if readIdleTimeout != 0 {
t = time.AfterFunc(readIdleTimeout, cc.healthCheck)
defer t.Stop()
}
for { for {
f, err := cc.fr.ReadFrame() f, err := cc.fr.ReadFrame()
if t != nil {
t.Reset(readIdleTimeout)
}
if err != nil { if err != nil {
cc.vlogf("http2: Transport readFrame error on conn %p: (%T) %v", cc, err, err) cc.vlogf("http2: Transport readFrame error on conn %p: (%T) %v", cc, err, err)
} }
@ -1943,9 +1832,7 @@ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFra
return nil, errors.New("malformed response from server: malformed non-numeric status pseudo header") return nil, errors.New("malformed response from server: malformed non-numeric status pseudo header")
} }
regularFields := f.RegularFields() header := make(http.Header)
strs := make([]string, len(regularFields))
header := make(http.Header, len(regularFields))
res := &http.Response{ res := &http.Response{
Proto: "HTTP/2.0", Proto: "HTTP/2.0",
ProtoMajor: 2, ProtoMajor: 2,
@ -1953,7 +1840,7 @@ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFra
StatusCode: statusCode, StatusCode: statusCode,
Status: status + " " + http.StatusText(statusCode), Status: status + " " + http.StatusText(statusCode),
} }
for _, hf := range regularFields { for _, hf := range f.RegularFields() {
key := http.CanonicalHeaderKey(hf.Name) key := http.CanonicalHeaderKey(hf.Name)
if key == "Trailer" { if key == "Trailer" {
t := res.Trailer t := res.Trailer
@ -1965,18 +1852,7 @@ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFra
t[http.CanonicalHeaderKey(v)] = nil t[http.CanonicalHeaderKey(v)] = nil
}) })
} else { } else {
vv := header[key] header[key] = append(header[key], hf.Value)
if vv == nil && len(strs) > 0 {
// More than likely this will be a single-element key.
// Most headers aren't multi-valued.
// Set the capacity on strs[0] to 1, so any future append
// won't extend the slice into the other strings.
vv, strs = strs[:1:1], strs[1:]
vv[0] = hf.Value
header[key] = vv
} else {
header[key] = append(vv, hf.Value)
}
} }
} }
@ -2262,6 +2138,8 @@ func (rl *clientConnReadLoop) processData(f *DataFrame) error {
return nil return nil
} }
var errInvalidTrailers = errors.New("http2: invalid trailers")
func (rl *clientConnReadLoop) endStream(cs *clientStream) { func (rl *clientConnReadLoop) endStream(cs *clientStream) {
// TODO: check that any declared content-length matches, like // TODO: check that any declared content-length matches, like
// server.go's (*stream).endStream method. // server.go's (*stream).endStream method.
@ -2492,6 +2370,7 @@ func (cc *ClientConn) writeStreamReset(streamID uint32, code ErrCode, err error)
var ( var (
errResponseHeaderListSize = errors.New("http2: response header list larger than advertised limit") errResponseHeaderListSize = errors.New("http2: response header list larger than advertised limit")
errRequestHeaderListSize = errors.New("http2: request header list larger than peer's advertised limit") errRequestHeaderListSize = errors.New("http2: request header list larger than peer's advertised limit")
errPseudoTrailers = errors.New("http2: invalid pseudo header in trailers")
) )
func (cc *ClientConn) logf(format string, args ...interface{}) { func (cc *ClientConn) logf(format string, args ...interface{}) {
@ -2525,13 +2404,11 @@ func strSliceContains(ss []string, s string) bool {
type erringRoundTripper struct{ err error } type erringRoundTripper struct{ err error }
func (rt erringRoundTripper) RoundTripErr() error { return rt.err }
func (rt erringRoundTripper) RoundTrip(*http.Request) (*http.Response, error) { return nil, rt.err } func (rt erringRoundTripper) RoundTrip(*http.Request) (*http.Response, error) { return nil, rt.err }
// gzipReader wraps a response body so it can lazily // gzipReader wraps a response body so it can lazily
// call gzip.NewReader on the first call to Read // call gzip.NewReader on the first call to Read
type gzipReader struct { type gzipReader struct {
_ incomparable
body io.ReadCloser // underlying Response.Body body io.ReadCloser // underlying Response.Body
zr *gzip.Reader // lazily-initialized gzip reader zr *gzip.Reader // lazily-initialized gzip reader
zerr error // sticky error zerr error // sticky error

View File

@ -149,7 +149,7 @@ func (n *priorityNode) addBytes(b int64) {
} }
// walkReadyInOrder iterates over the tree in priority order, calling f for each node // walkReadyInOrder iterates over the tree in priority order, calling f for each node
// with a non-empty write queue. When f returns true, this function returns true and the // with a non-empty write queue. When f returns true, this funcion returns true and the
// walk halts. tmp is used as scratch space for sorting. // walk halts. tmp is used as scratch space for sorting.
// //
// f(n, openParent) takes two arguments: the node to visit, n, and a bool that is true // f(n, openParent) takes two arguments: the node to visit, n, and a bool that is true

View File

@ -19,8 +19,7 @@ type randomWriteScheduler struct {
zero writeQueue zero writeQueue
// sq contains the stream-specific queues, keyed by stream ID. // sq contains the stream-specific queues, keyed by stream ID.
// When a stream is idle, closed, or emptied, it's deleted // When a stream is idle or closed, it's deleted from the map.
// from the map.
sq map[uint32]*writeQueue sq map[uint32]*writeQueue
// pool of empty queues for reuse. // pool of empty queues for reuse.
@ -64,12 +63,8 @@ func (ws *randomWriteScheduler) Pop() (FrameWriteRequest, bool) {
return ws.zero.shift(), true return ws.zero.shift(), true
} }
// Iterate over all non-idle streams until finding one that can be consumed. // Iterate over all non-idle streams until finding one that can be consumed.
for streamID, q := range ws.sq { for _, q := range ws.sq {
if wr, ok := q.consume(math.MaxInt32); ok { if wr, ok := q.consume(math.MaxInt32); ok {
if q.empty() {
delete(ws.sq, streamID)
ws.queuePool.put(q)
}
return wr, true return wr, true
} }
} }

View File

@ -1,6 +1,6 @@
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
// +build go1.13,!go1.14 // +build go1.13
package idna package idna

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +0,0 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !race
package socket
func (m *Message) raceRead() {
}
func (m *Message) raceWrite() {
}

View File

@ -1,37 +0,0 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build race
package socket
import (
"runtime"
"unsafe"
)
// This package reads and writes the Message buffers using a
// direct system call, which the race detector can't see.
// These functions tell the race detector what is going on during the syscall.
func (m *Message) raceRead() {
for _, b := range m.Buffers {
if len(b) > 0 {
runtime.RaceReadRange(unsafe.Pointer(&b[0]), len(b))
}
}
if b := m.OOB; len(b) > 0 {
runtime.RaceReadRange(unsafe.Pointer(&b[0]), len(b))
}
}
func (m *Message) raceWrite() {
for _, b := range m.Buffers {
if len(b) > 0 {
runtime.RaceWriteRange(unsafe.Pointer(&b[0]), len(b))
}
}
if b := m.OOB; len(b) > 0 {
runtime.RaceWriteRange(unsafe.Pointer(&b[0]), len(b))
}
}

View File

@ -13,9 +13,6 @@ import (
) )
func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) { func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) {
for i := range ms {
ms[i].raceWrite()
}
hs := make(mmsghdrs, len(ms)) hs := make(mmsghdrs, len(ms))
var parseFn func([]byte, string) (net.Addr, error) var parseFn func([]byte, string) (net.Addr, error)
if c.network != "tcp" { if c.network != "tcp" {
@ -46,9 +43,6 @@ func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) {
} }
func (c *Conn) sendMsgs(ms []Message, flags int) (int, error) { func (c *Conn) sendMsgs(ms []Message, flags int) (int, error) {
for i := range ms {
ms[i].raceRead()
}
hs := make(mmsghdrs, len(ms)) hs := make(mmsghdrs, len(ms))
var marshalFn func(net.Addr) []byte var marshalFn func(net.Addr) []byte
if c.network != "tcp" { if c.network != "tcp" {

View File

@ -12,7 +12,6 @@ import (
) )
func (c *Conn) recvMsg(m *Message, flags int) error { func (c *Conn) recvMsg(m *Message, flags int) error {
m.raceWrite()
var h msghdr var h msghdr
vs := make([]iovec, len(m.Buffers)) vs := make([]iovec, len(m.Buffers))
var sa []byte var sa []byte
@ -49,7 +48,6 @@ func (c *Conn) recvMsg(m *Message, flags int) error {
} }
func (c *Conn) sendMsg(m *Message, flags int) error { func (c *Conn) sendMsg(m *Message, flags int) error {
m.raceRead()
var h msghdr var h msghdr
vs := make([]iovec, len(m.Buffers)) vs := make([]iovec, len(m.Buffers))
var sa []byte var sa []byte

View File

@ -4,29 +4,4 @@
package socket package socket
import ( func probeProtocolStack() int { return 4 }
"sync"
"syscall"
"unsafe"
)
// See version list in https://github.com/DragonFlyBSD/DragonFlyBSD/blob/master/sys/sys/param.h
var (
osreldateOnce sync.Once
osreldate uint32
)
// First __DragonFly_version after September 2019 ABI changes
// http://lists.dragonflybsd.org/pipermail/users/2019-September/358280.html
const _dragonflyABIChangeVersion = 500705
func probeProtocolStack() int {
osreldateOnce.Do(func() { osreldate, _ = syscall.SysctlUint32("kern.osreldate") })
var p uintptr
if int(unsafe.Sizeof(p)) == 8 && osreldate >= _dragonflyABIChangeVersion {
return int(unsafe.Sizeof(p))
}
// 64-bit Dragonfly before the September 2019 ABI changes still requires
// 32-bit aligned access to network subsystem.
return 4
}

View File

@ -53,6 +53,7 @@ type sockaddrInet6 struct {
const ( const (
sizeofIovec = 0x10 sizeofIovec = 0x10
sizeofMsghdr = 0x30 sizeofMsghdr = 0x30
sizeofMmsghdr = 0x38
sizeofCmsghdr = 0xc sizeofCmsghdr = 0xc
sizeofSockaddrInet = 0x10 sizeofSockaddrInet = 0x10

View File

@ -47,6 +47,7 @@ type sockaddrInet6 struct {
const ( const (
sizeofIovec = 0x8 sizeofIovec = 0x8
sizeofMsghdr = 0x1c sizeofMsghdr = 0x1c
sizeofMmsghdr = 0x20
sizeofCmsghdr = 0xc sizeofCmsghdr = 0xc
sizeofSockaddrInet = 0x10 sizeofSockaddrInet = 0x10

View File

@ -50,6 +50,7 @@ type sockaddrInet6 struct {
const ( const (
sizeofIovec = 0x10 sizeofIovec = 0x10
sizeofMsghdr = 0x38 sizeofMsghdr = 0x38
sizeofMmsghdr = 0x40
sizeofCmsghdr = 0x10 sizeofCmsghdr = 0x10
sizeofSockaddrInet = 0x10 sizeofSockaddrInet = 0x10

View File

@ -45,9 +45,9 @@ type sockaddrInet6 struct {
} }
const ( const (
sizeofIovec = 0x8 sizeofIovec = 0x8
sizeofMsghdr = 0x1c sizeofMsghdr = 0x1c
sizeofMmsghdr = 0x20
sizeofCmsghdr = 0xc sizeofCmsghdr = 0xc
sizeofSockaddrInet = 0x10 sizeofSockaddrInet = 0x10

Some files were not shown because too many files have changed in this diff Show More