Skip to content
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ make
sudo make install
```

If you plan to use the `wolftls` subpackage and need concurrent `Read` and
`Write` on a single `Conn` to run in parallel, add `--enable-writedup` to the
`./configure` line above. Otherwise, the calls will be serialized.

Then clone the go-wolfssl repo and run the `./generateOptions.sh` script to customize go-wolfssl to the same feature set as wolfSSL. This script will generate an `options.go` file that will keep go-wolfssl and wolfSSL in sync. `generateOptions` should be run any time you change your wolfSSL configure options. If the path to your wolfSSL directory is `../wolfssl`, just run:
```
git clone https://github.com/wolfSSL/go-wolfssl
Expand Down
2 changes: 1 addition & 1 deletion aes.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ func Wc_AesGcm_Appended_Tag_Encrypt(aes *C.struct_Aes, outCipher, inPlain, inIv,
if len(outCipher) < (len(inPlain) + AES_BLOCK_SIZE) {
longOutCipher = make([]byte, len(inPlain) + AES_BLOCK_SIZE)
} else {
longOutCipher = outCipher
longOutCipher = outCipher[:len(inPlain) + AES_BLOCK_SIZE]
}

ret := Wc_AesGcmEncrypt(aes, longOutCipher[:(len(longOutCipher)-AES_BLOCK_SIZE)], inPlain, inIv, outAuthTag[:], inAAD)
Expand Down
21 changes: 21 additions & 0 deletions ecc.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,27 @@ package wolfSSL
// byte* out, word32* outlen) {
// return -174;
// }
// int wc_ecc_export_public_raw(ecc_key* key, byte* qx, word32* qxLen,
// byte* qy, word32* qyLen) {
// return -174;
// }
// int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx,
// ecc_key* key, word32 inSz) {
// return -174;
// }
// int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) {
// return -174;
// }
// int wc_EccPrivateKeyToDer(ecc_key* key, byte* output, word32 inLen) {
// return -174;
// }
// int wc_EccKeyToPKCS8(ecc_key* key, byte* output, word32* outLen) {
// return -174;
// }
// int wc_EccPublicKeyToDer(ecc_key* key, byte* output, word32 inLen,
// int with_AlgCurve) {
// return -174;
// }
// #endif
//
// /* Negate an ECC private key: d' = order - d, then regenerate the public key */
Expand Down
1 change: 1 addition & 0 deletions examples/server/server-psk.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ func main() {
conn, err := l.Accept()
if err != nil {
fmt.Println("Error accepting: ", err.Error())
os.Exit(1)
}

/* Create a WOLFSSL object */
Expand Down
1 change: 1 addition & 0 deletions examples/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ func main() {
conn, err := l.Accept()
if err != nil {
fmt.Println("Error accepting: ", err.Error())
os.Exit(1)
}

/* Create a WOLFSSL object */
Expand Down
4 changes: 4 additions & 0 deletions examples/x509/certVerify.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ func loadX509(certData []byte) *wolfSSL.WOLFSSL_X509 {
}

func main() {
wolfSSL.WolfSSL_Init()

Comment thread
mattia-moffa marked this conversation as resolved.
caPath := "../certs/ca-cert.pem"
int1Path := "../certs/ca-int-cert.pem"
int2Path := "../certs/ca-int2-cert.pem"
Expand Down Expand Up @@ -117,5 +119,7 @@ func main() {
}

fmt.Println("Certificate chain verified successfully.")

wolfSSL.WolfSSL_Cleanup()
}

4 changes: 4 additions & 0 deletions examples/x509/extractKey.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ func loadX509(certData []byte) *wolfSSL.WOLFSSL_X509 {
}

func main() {
wolfSSL.WolfSSL_Init()

Comment thread
mattia-moffa marked this conversation as resolved.
leafPath := "../certs/server-ecc.pem"


Expand Down Expand Up @@ -98,5 +100,7 @@ func main() {
fmt.Println("Successfully imported ECC public key structure from DER buffer")

wolfSSL.Wc_ecc_free(&pubKey)

wolfSSL.WolfSSL_Cleanup()
}

3 changes: 3 additions & 0 deletions sha.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ package wolfSSL
// int wc_Sha256Final(wc_Sha256* sha, byte* hash) {
// return -174;
// }
// int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst) {
// return -174;
// }
// #endif
import "C"
import (
Expand Down
6 changes: 6 additions & 0 deletions wolftls/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,9 @@ whose entire handshake and record I/O runs through wolfSSL.
- Per-connection callbacks: SNI (`Config.GetCertificate` /
`GetConfigForClient`) and cert-setup; trampolines and Go I/O
bridging are implemented in `callbacks.go`.

## Build requirements

Running `Read` and `Write` concurrently on a single `Conn` requires wolfSSL
built with `--enable-writedup`; otherwise the two calls will serialize on a
shared mutex.
55 changes: 49 additions & 6 deletions wolftls/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,15 @@ type Conn struct {
// a past deadline on c.conn.
mu sync.RWMutex

// muRead/muWrite serialize wolfSSL_read/wolfSSL_write. Aliased to the
// same mutex when HAVE_WRITE_DUP unavailable.
muRead *sync.Mutex
muWrite *sync.Mutex

// wolfSSL objects — created during handshake
ctx *wolfSSL.WOLFSSL_CTX
ssl *wolfSSL.WOLFSSL
ctx *wolfSSL.WOLFSSL_CTX
ssl *wolfSSL.WOLFSSL
sslWrite *wolfSSL.WOLFSSL // == ssl when HAVE_WRITE_DUP unavailable

// callback registration IDs (0 = none)
ioConnID int
Expand Down Expand Up @@ -402,6 +408,19 @@ func (c *Conn) doHandshake() error {
}
}

// Split off a write-only WOLFSSL when HAVE_WRITE_DUP is built in;
// otherwise fall back to a single mutex serializing Read and Write.
if dup := wolfSSL.WolfSSL_write_dup(c.ssl); dup != nil {
c.sslWrite = dup
c.muRead = &sync.Mutex{}
c.muWrite = &sync.Mutex{}
} else {
c.sslWrite = c.ssl
shared := &sync.Mutex{}
c.muRead = shared
c.muWrite = shared
}

return nil
}

Expand Down Expand Up @@ -462,6 +481,8 @@ func (c *Conn) Read(b []byte) (int, error) {
if c.ssl == nil {
return 0, net.ErrClosed
}
c.muRead.Lock()
defer c.muRead.Unlock()
n := wolfSSL.WolfSSL_read(c.ssl, b, uintptr(len(b)))
if n > 0 {
return n, nil
Expand Down Expand Up @@ -490,14 +511,16 @@ func (c *Conn) Write(b []byte) (int, error) {
}
c.mu.RLock()
defer c.mu.RUnlock()
if c.ssl == nil {
if c.sslWrite == nil {
return 0, net.ErrClosed
}
c.muWrite.Lock()
defer c.muWrite.Unlock()
total := 0
for total < len(b) {
n := wolfSSL.WolfSSL_write(c.ssl, b[total:], uintptr(len(b)-total))
n := wolfSSL.WolfSSL_write(c.sslWrite, b[total:], uintptr(len(b)-total))
if n <= 0 {
errCode := wolfSSL.WolfSSL_get_error(c.ssl, n)
errCode := wolfSSL.WolfSSL_get_error(c.sslWrite, n)
errMsg := wolfSSL.WolfSSL_ERR_error_string(errCode, nil)
return total, fmt.Errorf("wolftls: write error: %s (%d)", errMsg, errCode)
}
Expand Down Expand Up @@ -537,6 +560,8 @@ func (c *Conn) Close() error {

// LocalAddr returns the local network address of the underlying connection.
func (c *Conn) LocalAddr() net.Addr {
c.mu.RLock()
defer c.mu.RUnlock()
if c.conn == nil {
return nil
}
Expand All @@ -545,6 +570,8 @@ func (c *Conn) LocalAddr() net.Addr {

// RemoteAddr returns the remote network address of the underlying connection.
func (c *Conn) RemoteAddr() net.Addr {
c.mu.RLock()
defer c.mu.RUnlock()
if c.conn == nil {
return nil
}
Expand All @@ -554,6 +581,8 @@ func (c *Conn) RemoteAddr() net.Addr {
// SetDeadline sets the read and write deadlines on the underlying connection.
// wolfSSL will observe these via the file descriptor's socket timeout.
func (c *Conn) SetDeadline(t time.Time) error {
c.mu.RLock()
defer c.mu.RUnlock()
if c.conn == nil {
return errors.New("wolftls: connection closed")
}
Expand All @@ -562,6 +591,8 @@ func (c *Conn) SetDeadline(t time.Time) error {

// SetReadDeadline sets the read deadline on the underlying connection.
func (c *Conn) SetReadDeadline(t time.Time) error {
c.mu.RLock()
defer c.mu.RUnlock()
if c.conn == nil {
return errors.New("wolftls: connection closed")
}
Expand All @@ -570,6 +601,8 @@ func (c *Conn) SetReadDeadline(t time.Time) error {

// SetWriteDeadline sets the write deadline on the underlying connection.
func (c *Conn) SetWriteDeadline(t time.Time) error {
c.mu.RLock()
defer c.mu.RUnlock()
if c.conn == nil {
return errors.New("wolftls: connection closed")
}
Expand All @@ -578,6 +611,8 @@ func (c *Conn) SetWriteDeadline(t time.Time) error {

// NetConn returns the underlying net.Conn, or nil if the connection is closed.
func (c *Conn) NetConn() net.Conn {
c.mu.RLock()
defer c.mu.RUnlock()
if rc, ok := c.conn.(*recordingConn); ok {
return rc.Conn
}
Expand All @@ -602,10 +637,18 @@ func (c *Conn) freeSSLLocked() {
if c.conn != nil {
c.conn.SetDeadline(time.Now().Add(100 * time.Millisecond))
}
wolfSSL.WolfSSL_shutdown(c.ssl)
shutdownSSL := c.ssl
if c.sslWrite != nil {
shutdownSSL = c.sslWrite
}
wolfSSL.WolfSSL_shutdown(shutdownSSL)
if c.conn != nil {
c.conn.SetDeadline(time.Time{}) // clear deadline
}
if c.sslWrite != nil && c.sslWrite != c.ssl {
wolfSSL.WolfSSL_free(c.sslWrite)
}
c.sslWrite = nil
wolfSSL.WolfSSL_free(c.ssl)
c.ssl = nil
}
Expand Down
4 changes: 4 additions & 0 deletions wolftls/tls_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1139,6 +1139,10 @@ func TestConcurrentReadWrite(t *testing.T) {
cli, srv, cleanup := setupPair(t)
defer cleanup()

if cli.sslWrite == cli.ssl {
t.Skip("wolfSSL built without HAVE_WRITE_DUP; concurrent Read+Write serialized")
}

const messages = 100
const msgSize = 512

Expand Down
4 changes: 4 additions & 0 deletions wolfx509/certgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,10 @@ func translateExtKeyUsage(uses []ExtKeyUsage) int {
out |= wcExtKeyUsageCodeSigning
case ExtKeyUsageEmailProtection:
out |= wcExtKeyUsageEmailProt
case ExtKeyUsageTimeStamping:
out |= wcExtKeyUsageTimestamp
case ExtKeyUsageOCSPSigning:
out |= wcExtKeyUsageOCSPSign
}
}
return out
Expand Down
4 changes: 3 additions & 1 deletion wolfx509/certgen_wolfcrypt.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

package wolfx509

// #cgo CFLAGS: -g -Wall -DWC_CTC_NAME_SIZE=256 -I/usr/include -I/usr/include/wolfssl -I/usr/local/include -I/usr/local/include/wolfssl
// #cgo CFLAGS: -g -Wall -I/usr/include -I/usr/include/wolfssl -I/usr/local/include -I/usr/local/include/wolfssl
// #cgo LDFLAGS: -L/usr/local/lib -lwolfssl -lm
// #include <stdlib.h>
// #include <string.h>
Expand Down Expand Up @@ -87,6 +87,8 @@ const (
wcExtKeyUsageClientAuth = 0x04
wcExtKeyUsageCodeSigning = 0x08
wcExtKeyUsageEmailProt = 0x10
wcExtKeyUsageTimestamp = 0x20
wcExtKeyUsageOCSPSign = 0x40
)

// sigTypeFor maps a key algorithm to its wolfCrypt CTC_* sigType.
Expand Down
Loading