From ce6c45e481a59d843a3b9caab55608c738aac2f4 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Fri, 18 Oct 2019 10:59:08 +0300 Subject: [PATCH] PRF_IPSEC_PRFPLUS_GOSTR3411_2012_{256,512} --- INSTALL | 18 +++++----- NEWS | 6 +++- VERSION | 2 +- download.texi | 18 +++++----- makedist.sh | 1 + news.texi | 8 +++++ prfplus/gost.go | 46 +++++++++++++++++++++++++ prfplus/gost_test.go | 81 ++++++++++++++++++++++++++++++++++++++++++++ prfplus/plus.go | 47 +++++++++++++++++++++++++ 9 files changed, 207 insertions(+), 20 deletions(-) create mode 100644 prfplus/gost.go create mode 100644 prfplus/gost_test.go create mode 100644 prfplus/plus.go diff --git a/INSTALL b/INSTALL index 06e6e67..22565ef 100644 --- a/INSTALL +++ b/INSTALL @@ -1,19 +1,19 @@ Preferable way is to download tarball with the signature from official website and, for example, run tests with benchmarks: - $ wget http://gogost.cypherpunks.ru/gogost-4.1.0.tar.xz - $ wget http://gogost.cypherpunks.ru/gogost-4.1.0.tar.xz.sig - $ gpg --verify gogost-4.1.0.tar.xz.sig gogost-4.1.0.tar.xz - $ xz -d < gogost-4.1.0.tar.xz | tar xf - - $ make -C gogost-4.1.0 all bench - $ echo hello world | ./gogost-4.1.0/streebog256 + $ wget http://gogost.cypherpunks.ru/gogost-4.2.0.tar.xz + $ wget http://gogost.cypherpunks.ru/gogost-4.2.0.tar.xz.sig + $ gpg --verify gogost-4.2.0.tar.xz.sig gogost-4.2.0.tar.xz + $ xz -d < gogost-4.2.0.tar.xz | tar xf - + $ make -C gogost-4.2.0 all bench + $ echo hello world | ./gogost-4.2.0/streebog256 f72018189a5cfb803dbe1f2149cf554c40093d8e7f81c21e08ac5bcd09d9934d And then you can include its source code in your project for example like this: $ mkdir -p myproj/src - $ cp -r gogost-4.1.0/src/go.cypherpunks.ru myproj/src + $ cp -r gogost-4.2.0/src/go.cypherpunks.ru myproj/src $ export GOPATH=$PWD/myproj $ cd myproj/src $ cat > main.go < /home/stargrave/gogost-4.1.0/src/go.cypherpunks.ru/gogost/v4 + require go.cypherpunks.ru/gogost/v4 v4.2.0 + replace go.cypherpunks.ru/gogost/v4 => /home/stargrave/gogost-4.2.0/src/go.cypherpunks.ru/gogost/v4 diff --git a/NEWS b/NEWS index 5b13d25..1723442 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,9 @@ +4.2.0: + * PRF_IPSEC_PRFPLUS_GOSTR3411_2012_{256,512} implementation + * Generic prf+ function (taken from IKEv2) implementation + 4.1.0: - * ESPTREE implementation + * ESPTREE/IKETREE implementation * CurveIdtc26gost34102012256paramSetB, CurveIdtc26gost34102012256paramSetC, CurveIdtc26gost34102012256paramSetD curve aliases * Forbid any later GNU GPL version autousage diff --git a/VERSION b/VERSION index ee74734..6aba2b2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.1.0 +4.2.0 diff --git a/download.texi b/download.texi index e264247..fde8fda 100644 --- a/download.texi +++ b/download.texi @@ -5,12 +5,12 @@ Preferable way is to download tarball with the signature from website and, for example, run tests with benchmarks: @verbatim -$ wget http://gogost.cypherpunks.ru/gogost-4.1.0.tar.xz -$ wget http://gogost.cypherpunks.ru/gogost-4.1.0.tar.xz.sig -$ gpg --verify gogost-4.1.0.tar.xz.sig gogost-4.1.0.tar.xz -$ xz -d < gogost-4.1.0.tar.xz | tar xf - -$ make -C gogost-4.1.0 all bench -$ echo hello world | ./gogost-4.1.0/streebog256 +$ wget http://gogost.cypherpunks.ru/gogost-4.2.0.tar.xz +$ wget http://gogost.cypherpunks.ru/gogost-4.2.0.tar.xz.sig +$ gpg --verify gogost-4.2.0.tar.xz.sig gogost-4.2.0.tar.xz +$ xz -d < gogost-4.2.0.tar.xz | tar xf - +$ make -C gogost-4.2.0 all bench +$ echo hello world | ./gogost-4.2.0/streebog256 f72018189a5cfb803dbe1f2149cf554c40093d8e7f81c21e08ac5bcd09d9934d @end verbatim @@ -19,7 +19,7 @@ like this: @verbatim $ mkdir -p myproj/src -$ cp -r gogost-4.1.0/src/go.cypherpunks.ru myproj/src +$ cp -r gogost-4.2.0/src/go.cypherpunks.ru myproj/src $ export GOPATH=$PWD/myproj $ cd myproj/src $ cat > main.go < /home/stargrave/gogost-4.1.0/src/go.cypherpunks.ru/gogost/v4 +require go.cypherpunks.ru/gogost/v4 v4.2.0 +replace go.cypherpunks.ru/gogost/v4 => /home/stargrave/gogost-4.2.0/src/go.cypherpunks.ru/gogost/v4 @end verbatim You can obtain development source code with diff --git a/makedist.sh b/makedist.sh index 7ed9a15..879a373 100755 --- a/makedist.sh +++ b/makedist.sh @@ -22,6 +22,7 @@ mv \ gost341264 \ gost3413 \ mgm \ + prfplus \ cmd internal gogost.go go.mod go.sum src/$mod_name mkdir -p src/golang.org/x/crypto diff --git a/news.texi b/news.texi index 7e09a27..01fb655 100644 --- a/news.texi +++ b/news.texi @@ -3,6 +3,14 @@ @table @strong +@anchor{Release 4.2.0} +@item 4.2.0 + @itemize + @item @code{PRF_IPSEC_PRFPLUS_GOSTR3411_2012_@{256,512@}} implementation + @item Generic @code{prf+} function (taken from IKEv2 + (@url{https://tools.ietf.org/html/rfc5831.html, RFC 7296})) + @end itemize + @anchor{Release 4.1.0} @item 4.1.0 @itemize diff --git a/prfplus/gost.go b/prfplus/gost.go new file mode 100644 index 0000000..659b5b4 --- /dev/null +++ b/prfplus/gost.go @@ -0,0 +1,46 @@ +// GoGOST -- Pure Go GOST cryptographic functions library +// Copyright (C) 2015-2019 Sergey Matveev +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 3 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// PRF_IPSEC_PRFPLUS_GOSTR3411_2012_{256,512} as defined in R 50.1.113-2016. +package prfplus + +import ( + "crypto/hmac" + "hash" + + "go.cypherpunks.ru/gogost/v4/gost34112012256" + "go.cypherpunks.ru/gogost/v4/gost34112012512" +) + +type PRFIPsecPRFPlusGOSTR34112012 struct{ h hash.Hash } + +func NewPRFIPsecPRFPlusGOSTR34112012256(key []byte) PRFForPlus { + return PRFIPsecPRFPlusGOSTR34112012{hmac.New(gost34112012256.New, key)} +} + +func NewPRFIPsecPRFPlusGOSTR34112012512(key []byte) PRFForPlus { + return PRFIPsecPRFPlusGOSTR34112012{hmac.New(gost34112012512.New, key)} +} + +func (prf PRFIPsecPRFPlusGOSTR34112012) BlockSize() int { + return prf.h.Size() +} + +func (prf PRFIPsecPRFPlusGOSTR34112012) Derive(salt []byte) []byte { + prf.h.Write(salt) + sum := prf.h.Sum(nil) + prf.h.Reset() + return sum +} diff --git a/prfplus/gost_test.go b/prfplus/gost_test.go new file mode 100644 index 0000000..300d76c --- /dev/null +++ b/prfplus/gost_test.go @@ -0,0 +1,81 @@ +// GoGOST -- Pure Go GOST cryptographic functions library +// Copyright (C) 2015-2019 Sergey Matveev +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 3 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package prfplus + +import ( + "bytes" + "testing" +) + +func TestPRFIPsecPRFPlusGOSTR34112012256(t *testing.T) { + prf := NewPRFIPsecPRFPlusGOSTR34112012256([]byte{ + 0xC9, 0xA9, 0xA7, 0x73, 0x20, 0xE2, 0xCC, 0x55, + 0x9E, 0xD7, 0x2D, 0xCE, 0x6F, 0x47, 0xE2, 0x19, + 0x2C, 0xCE, 0xA9, 0x5F, 0xA6, 0x48, 0x67, 0x05, + 0x82, 0xC0, 0x54, 0xC0, 0xEF, 0x36, 0xC2, 0x21, + }) + dst := make([]byte, 64) + PRFPlus(prf, dst, []byte{ + 0x01, 0x26, 0xBD, 0xB8, 0x78, 0x00, 0x1D, 0x80, + 0x60, 0x3C, 0x85, 0x44, 0xC7, 0x27, 0x01, 0x00, + }) + if bytes.Compare(dst, []byte{ + 0x2D, 0xE5, 0xEE, 0x84, 0xE1, 0x3D, 0x7B, 0xE5, + 0x36, 0x16, 0x67, 0x39, 0x13, 0x37, 0x0A, 0xB0, + 0x54, 0xC0, 0x74, 0xB7, 0x9B, 0x69, 0xA8, 0xA8, + 0x46, 0x82, 0xA9, 0xF0, 0x4F, 0xEC, 0xD5, 0x87, + 0x29, 0xF6, 0x0D, 0xDA, 0x45, 0x7B, 0xF2, 0x19, + 0xAA, 0x2E, 0xF9, 0x5D, 0x7A, 0x59, 0xBE, 0x95, + 0x4D, 0xE0, 0x08, 0xF4, 0xA5, 0x0D, 0x50, 0x4D, + 0xBD, 0xB6, 0x90, 0xBE, 0x68, 0x06, 0x01, 0x53, + }) != 0 { + t.FailNow() + } +} + +func TestPRFIPsecPRFPlusGOSTR34112012512(t *testing.T) { + prf := NewPRFIPsecPRFPlusGOSTR34112012512([]byte{ + 0xC9, 0xA9, 0xA7, 0x73, 0x20, 0xE2, 0xCC, 0x55, + 0x9E, 0xD7, 0x2D, 0xCE, 0x6F, 0x47, 0xE2, 0x19, + 0x2C, 0xCE, 0xA9, 0x5F, 0xA6, 0x48, 0x67, 0x05, + 0x82, 0xC0, 0x54, 0xC0, 0xEF, 0x36, 0xC2, 0x21, + }) + dst := make([]byte, 128) + PRFPlus(prf, dst, []byte{ + 0x01, 0x26, 0xBD, 0xB8, 0x78, 0x00, 0x1D, 0x80, + 0x60, 0x3C, 0x85, 0x44, 0xC7, 0x27, 0x01, 0x00, + }) + if bytes.Compare(dst, []byte{ + 0x5D, 0xA6, 0x71, 0x43, 0xA5, 0xF1, 0x2A, 0x6D, + 0x6E, 0x47, 0x42, 0x59, 0x6F, 0x39, 0x24, 0x3F, + 0xCC, 0x61, 0x57, 0x45, 0x91, 0x5B, 0x32, 0x59, + 0x10, 0x06, 0xFF, 0x78, 0xA2, 0x08, 0x63, 0xD5, + 0xF8, 0x8E, 0x4A, 0xFC, 0x17, 0xFB, 0xBE, 0x70, + 0xB9, 0x50, 0x95, 0x73, 0xDB, 0x00, 0x5E, 0x96, + 0x26, 0x36, 0x98, 0x46, 0xCB, 0x86, 0x19, 0x99, + 0x71, 0x6C, 0x16, 0x5D, 0xD0, 0x6A, 0x15, 0x85, + 0x48, 0x34, 0x49, 0x5A, 0x43, 0x74, 0x6C, 0xB5, + 0x3F, 0x0A, 0xBA, 0x3B, 0xC4, 0x6E, 0xBC, 0xF8, + 0x77, 0x3C, 0xA6, 0x4A, 0xD3, 0x43, 0xC1, 0x22, + 0xEE, 0x2A, 0x57, 0x75, 0x57, 0x03, 0x81, 0x57, + 0xEE, 0x9C, 0x38, 0x8D, 0x96, 0xEF, 0x71, 0xD5, + 0x8B, 0xE5, 0xC1, 0xEF, 0xA1, 0xAF, 0xA9, 0x5E, + 0xBE, 0x83, 0xE3, 0x9D, 0x00, 0xE1, 0x9A, 0x5D, + 0x03, 0xDC, 0xD6, 0x0A, 0x01, 0xBC, 0xA8, 0xE3, + }) != 0 { + t.FailNow() + } +} diff --git a/prfplus/plus.go b/prfplus/plus.go new file mode 100644 index 0000000..84ce70c --- /dev/null +++ b/prfplus/plus.go @@ -0,0 +1,47 @@ +// GoGOST -- Pure Go GOST cryptographic functions library +// Copyright (C) 2015-2019 Sergey Matveev +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 3 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package prfplus + +type PRFForPlus interface { + BlockSize() int + Derive(salt []byte) []byte +} + +// prf+ function as defined in RFC 7296 (IKEv2) +func PRFPlus(prf PRFForPlus, dst, salt []byte) { + in := make([]byte, prf.BlockSize()+len(salt)+1) + in[len(in)-1] = byte(0x01) + copy(in[prf.BlockSize():], salt) + copy(in[:prf.BlockSize()], prf.Derive(in[prf.BlockSize():])) + copy(dst, in[:prf.BlockSize()]) + n := len(dst) / prf.BlockSize() + if n == 0 { + return + } + if n*prf.BlockSize() != len(dst) { + n++ + } + n-- + out := dst[prf.BlockSize():] + for i := 0; i < n; i++ { + in[len(in)-1] = byte(i + 2) + copy(in[:prf.BlockSize()], prf.Derive(in)) + copy(out, in[:prf.BlockSize()]) + if i+1 != n { + out = out[prf.BlockSize():] + } + } +} -- 2.44.0