Skip to content

Commit

Permalink
[dev.boringcrypto] crypto/sha1,sha256,sha512: use BoringCrypto
Browse files Browse the repository at this point in the history
Change-Id: I80a764971b41f75c3b699797bfed71f509e3407d
Reviewed-on: https://go-review.googlesource.com/55474
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Adam Langley <agl@golang.org>
  • Loading branch information
rsc committed Aug 17, 2017
1 parent e0e2bbd commit 96d6718
Show file tree
Hide file tree
Showing 11 changed files with 306 additions and 3 deletions.
12 changes: 9 additions & 3 deletions src/crypto/internal/boring/notboring.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

package boring

import "hash"

const available = false

// Unreachable marks code that should be unreachable
Expand All @@ -18,8 +20,12 @@ func UnreachableExceptTests() {}

type randReader int

func (randReader) Read(b []byte) (int, error) {
panic("boringcrypto: not available")
}
func (randReader) Read(b []byte) (int, error) { panic("boringcrypto: not available") }

const RandReader = randReader(0)

func NewSHA1() hash.Hash { panic("boringcrypto: not available") }
func NewSHA224() hash.Hash { panic("boringcrypto: not available") }
func NewSHA256() hash.Hash { panic("boringcrypto: not available") }
func NewSHA384() hash.Hash { panic("boringcrypto: not available") }
func NewSHA512() hash.Hash { panic("boringcrypto: not available") }
175 changes: 175 additions & 0 deletions src/crypto/internal/boring/sha.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build linux,amd64
// +build !cmd_go_bootstrap

package boring

// #include "goboringcrypto.h"
import "C"
import (
"hash"
"unsafe"
)

// NewSHA1 returns a new SHA1 hash.
func NewSHA1() hash.Hash {
h := new(sha1Hash)
h.Reset()
return h
}

type sha1Hash struct {
ctx C.GO_SHA_CTX
out [20]byte
}

func (h *sha1Hash) Reset() { C._goboringcrypto_SHA1_Init(&h.ctx) }
func (h *sha1Hash) Size() int { return 20 }
func (h *sha1Hash) BlockSize() int { return 64 }
func (h *sha1Hash) Sum(in []byte) []byte { return append(in, h.sum()...) }

func (h *sha1Hash) Write(p []byte) (int, error) {
if len(p) > 0 && C._goboringcrypto_SHA1_Update(&h.ctx, unsafe.Pointer(&p[0]), C.size_t(len(p))) == 0 {
panic("boringcrypto: SHA1_Update failed")
}
return len(p), nil
}

func (h0 *sha1Hash) sum() []byte {
h := *h0 // make copy so future Write+Sum is valid
if C._goboringcrypto_SHA1_Final((*C.uint8_t)(unsafe.Pointer(&h.out[0])), &h.ctx) == 0 {
panic("boringcrypto: SHA1_Final failed")
}
return h.out[:]
}

// NewSHA224 returns a new SHA224 hash.
func NewSHA224() hash.Hash {
h := new(sha224Hash)
h.Reset()
return h
}

type sha224Hash struct {
ctx C.GO_SHA256_CTX
out [224 / 8]byte
}

func (h *sha224Hash) Reset() { C._goboringcrypto_SHA224_Init(&h.ctx) }
func (h *sha224Hash) Size() int { return 224 / 8 }
func (h *sha224Hash) BlockSize() int { return 64 }
func (h *sha224Hash) Sum(in []byte) []byte { return append(in, h.sum()...) }

func (h *sha224Hash) Write(p []byte) (int, error) {
if len(p) > 0 && C._goboringcrypto_SHA224_Update(&h.ctx, unsafe.Pointer(&p[0]), C.size_t(len(p))) == 0 {
panic("boringcrypto: SHA224_Update failed")
}
return len(p), nil
}

func (h0 *sha224Hash) sum() []byte {
h := *h0 // make copy so future Write+Sum is valid
if C._goboringcrypto_SHA224_Final((*C.uint8_t)(unsafe.Pointer(&h.out[0])), &h.ctx) == 0 {
panic("boringcrypto: SHA224_Final failed")
}
return h.out[:]
}

// NewSHA256 returns a new SHA256 hash.
func NewSHA256() hash.Hash {
h := new(sha256Hash)
h.Reset()
return h
}

type sha256Hash struct {
ctx C.GO_SHA256_CTX
out [256 / 8]byte
}

func (h *sha256Hash) Reset() { C._goboringcrypto_SHA256_Init(&h.ctx) }
func (h *sha256Hash) Size() int { return 256 / 8 }
func (h *sha256Hash) BlockSize() int { return 64 }
func (h *sha256Hash) Sum(in []byte) []byte { return append(in, h.sum()...) }

func (h *sha256Hash) Write(p []byte) (int, error) {
if len(p) > 0 && C._goboringcrypto_SHA256_Update(&h.ctx, unsafe.Pointer(&p[0]), C.size_t(len(p))) == 0 {
panic("boringcrypto: SHA256_Update failed")
}
return len(p), nil
}

func (h0 *sha256Hash) sum() []byte {
h := *h0 // make copy so future Write+Sum is valid
if C._goboringcrypto_SHA256_Final((*C.uint8_t)(unsafe.Pointer(&h.out[0])), &h.ctx) == 0 {
panic("boringcrypto: SHA256_Final failed")
}
return h.out[:]
}

// NewSHA384 returns a new SHA384 hash.
func NewSHA384() hash.Hash {
h := new(sha384Hash)
h.Reset()
return h
}

type sha384Hash struct {
ctx C.GO_SHA512_CTX
out [384 / 8]byte
}

func (h *sha384Hash) Reset() { C._goboringcrypto_SHA384_Init(&h.ctx) }
func (h *sha384Hash) Size() int { return 384 / 8 }
func (h *sha384Hash) BlockSize() int { return 128 }
func (h *sha384Hash) Sum(in []byte) []byte { return append(in, h.sum()...) }

func (h *sha384Hash) Write(p []byte) (int, error) {
if len(p) > 0 && C._goboringcrypto_SHA384_Update(&h.ctx, unsafe.Pointer(&p[0]), C.size_t(len(p))) == 0 {
panic("boringcrypto: SHA384_Update failed")
}
return len(p), nil
}

func (h0 *sha384Hash) sum() []byte {
h := *h0 // make copy so future Write+Sum is valid
if C._goboringcrypto_SHA384_Final((*C.uint8_t)(unsafe.Pointer(&h.out[0])), &h.ctx) == 0 {
panic("boringcrypto: SHA384_Final failed")
}
return h.out[:]
}

// NewSHA512 returns a new SHA512 hash.
func NewSHA512() hash.Hash {
h := new(sha512Hash)
h.Reset()
return h
}

type sha512Hash struct {
ctx C.GO_SHA512_CTX
out [512 / 8]byte
}

func (h *sha512Hash) Reset() { C._goboringcrypto_SHA512_Init(&h.ctx) }
func (h *sha512Hash) Size() int { return 512 / 8 }
func (h *sha512Hash) BlockSize() int { return 128 }
func (h *sha512Hash) Sum(in []byte) []byte { return append(in, h.sum()...) }

func (h *sha512Hash) Write(p []byte) (int, error) {
if len(p) > 0 && C._goboringcrypto_SHA512_Update(&h.ctx, unsafe.Pointer(&p[0]), C.size_t(len(p))) == 0 {
panic("boringcrypto: SHA512_Update failed")
}
return len(p), nil
}

func (h0 *sha512Hash) sum() []byte {
h := *h0 // make copy so future Write+Sum is valid
if C._goboringcrypto_SHA512_Final((*C.uint8_t)(unsafe.Pointer(&h.out[0])), &h.ctx) == 0 {
panic("boringcrypto: SHA512_Final failed")
}
return h.out[:]
}
22 changes: 22 additions & 0 deletions src/crypto/sha1/boring.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Extra indirection here so that when building go_bootstrap
// cmd/internal/boring is not even imported, so that we don't
// have to maintain changes to cmd/dist's deps graph.

// +build !cmd_go_bootstrap

package sha1

import (
"crypto/internal/boring"
"hash"
)

const boringEnabled = boring.Enabled

func boringNewSHA1() hash.Hash { return boring.NewSHA1() }

func boringUnreachable() { boring.Unreachable() }
17 changes: 17 additions & 0 deletions src/crypto/sha1/notboring.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build cmd_go_bootstrap

package sha1

import (
"hash"
)

const boringEnabled = false

func boringNewSHA1() hash.Hash { panic("boringcrypto: not available") }

func boringUnreachable() {}
12 changes: 12 additions & 0 deletions src/crypto/sha1/sha1.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ func (d *digest) Reset() {

// New returns a new hash.Hash computing the SHA1 checksum.
func New() hash.Hash {
if boringEnabled {
return boringNewSHA1()
}
d := new(digest)
d.Reset()
return d
Expand All @@ -62,6 +65,7 @@ func (d *digest) Size() int { return Size }
func (d *digest) BlockSize() int { return BlockSize }

func (d *digest) Write(p []byte) (nn int, err error) {
boringUnreachable()
nn = len(p)
d.len += uint64(nn)
if d.nx > 0 {
Expand All @@ -85,6 +89,7 @@ func (d *digest) Write(p []byte) (nn int, err error) {
}

func (d0 *digest) Sum(in []byte) []byte {
boringUnreachable()
// Make a copy of d0 so that caller can keep writing and summing.
d := *d0
hash := d.checkSum()
Expand Down Expand Up @@ -194,6 +199,13 @@ func (d *digest) constSum() [Size]byte {

// Sum returns the SHA-1 checksum of the data.
func Sum(data []byte) [Size]byte {
if boringEnabled {
h := New()
h.Write(data)
var ret [Size]byte
h.Sum(ret[:0])
return ret
}
var d digest
d.Reset()
d.Write(data)
Expand Down
7 changes: 7 additions & 0 deletions src/crypto/sha1/sha1_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
package sha1

import (
"crypto/internal/boring"
"crypto/rand"
"fmt"
"io"
Expand Down Expand Up @@ -73,6 +74,9 @@ func TestGolden(t *testing.T) {
io.WriteString(c, g.in[len(g.in)/2:])
sum = c.Sum(nil)
case 3:
if boring.Enabled {
continue
}
io.WriteString(c, g.in[0:len(g.in)/2])
c.(*digest).ConstantTimeSum(nil)
io.WriteString(c, g.in[len(g.in)/2:])
Expand Down Expand Up @@ -103,6 +107,9 @@ func TestBlockSize(t *testing.T) {

// Tests that blockGeneric (pure Go) and block (in assembly for some architectures) match.
func TestBlockGeneric(t *testing.T) {
if boring.Enabled {
t.Skip("BoringCrypto doesn't expose digest")
}
for i := 1; i < 30; i++ { // arbitrary factor
gen, asm := New().(*digest), New().(*digest)
buf := make([]byte, BlockSize*i)
Expand Down
23 changes: 23 additions & 0 deletions src/crypto/sha256/sha256.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package sha256

import (
"crypto"
"crypto/internal/boring"
"hash"
)

Expand Down Expand Up @@ -80,13 +81,19 @@ func (d *digest) Reset() {

// New returns a new hash.Hash computing the SHA256 checksum.
func New() hash.Hash {
if boring.Enabled {
return boring.NewSHA256()
}
d := new(digest)
d.Reset()
return d
}

// New224 returns a new hash.Hash computing the SHA224 checksum.
func New224() hash.Hash {
if boring.Enabled {
return boring.NewSHA224()
}
d := new(digest)
d.is224 = true
d.Reset()
Expand All @@ -103,6 +110,7 @@ func (d *digest) Size() int {
func (d *digest) BlockSize() int { return BlockSize }

func (d *digest) Write(p []byte) (nn int, err error) {
boring.Unreachable()
nn = len(p)
d.len += uint64(nn)
if d.nx > 0 {
Expand All @@ -126,6 +134,7 @@ func (d *digest) Write(p []byte) (nn int, err error) {
}

func (d0 *digest) Sum(in []byte) []byte {
boring.Unreachable()
// Make a copy of d0 so that caller can keep writing and summing.
d := *d0
hash := d.checkSum()
Expand Down Expand Up @@ -175,6 +184,13 @@ func (d *digest) checkSum() [Size]byte {

// Sum256 returns the SHA256 checksum of the data.
func Sum256(data []byte) [Size]byte {
if boring.Enabled {
h := New()
h.Write(data)
var ret [Size]byte
h.Sum(ret[:0])
return ret
}
var d digest
d.Reset()
d.Write(data)
Expand All @@ -183,6 +199,13 @@ func Sum256(data []byte) [Size]byte {

// Sum224 returns the SHA224 checksum of the data.
func Sum224(data []byte) (sum224 [Size224]byte) {
if boring.Enabled {
h := New224()
h.Write(data)
var ret [Size224]byte
h.Sum(ret[:0])
return ret
}
var d digest
d.is224 = true
d.Reset()
Expand Down
4 changes: 4 additions & 0 deletions src/crypto/sha256/sha256_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
package sha256

import (
"crypto/internal/boring"
"crypto/rand"
"fmt"
"io"
Expand Down Expand Up @@ -153,6 +154,9 @@ func TestBlockSize(t *testing.T) {

// Tests that blockGeneric (pure Go) and block (in assembly for some architectures) match.
func TestBlockGeneric(t *testing.T) {
if boring.Enabled {
t.Skip("BoringCrypto doesn't expose digest")
}
gen, asm := New().(*digest), New().(*digest)
buf := make([]byte, BlockSize*20) // arbitrary factor
rand.Read(buf)
Expand Down
Loading

0 comments on commit 96d6718

Please sign in to comment.