|
package main |
|
|
|
import ( |
|
"log" |
|
"net" |
|
"runtime" |
|
"runtime/debug" |
|
"sync" |
|
|
|
"github.com/SpaceMonkeyGo/openssl" |
|
) |
|
|
|
var ( |
|
certBytes = []byte(`-----BEGIN CERTIFICATE----- |
|
MIIDxDCCAqygAwIBAgIVAMcK/0VWQr2O3MNfJCydqR7oVELcMA0GCSqGSIb3DQEB |
|
BQUAMIGQMUkwRwYDVQQDE0A1NjdjZGRmYzRjOWZiNTYwZTk1M2ZlZjA1N2M0NGFm |
|
MDdiYjc4MDIzODIxYTA5NThiY2RmMGMwNzJhOTdiMThhMQswCQYDVQQGEwJVUzEN |
|
MAsGA1UECBMEVXRhaDEQMA4GA1UEBxMHTWlkdmFsZTEVMBMGA1UEChMMU3BhY2Ug |
|
TW9ua2V5MB4XDTEzMTIxNzE4MzgyMloXDTIzMTIxNTE4MzgyMlowgZAxSTBHBgNV |
|
BAMTQDM4NTg3ODRkMjU1NTdiNTM1MWZmNjRmMmQzMTQ1ZjkwYTJlMTIzMDM4Y2Yz |
|
Mjc1Yzg1OTM1MjcxYWIzMmNiMDkxCzAJBgNVBAYTAlVTMQ0wCwYDVQQIEwRVdGFo |
|
MRAwDgYDVQQHEwdNaWR2YWxlMRUwEwYDVQQKEwxTcGFjZSBNb25rZXkwggEiMA0G |
|
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDdf3icNvFsrlrnNLi8SocscqlSbFq+ |
|
pEvmhcSoqgDLqebnqu8Ld73HJJ74MGXEgRX8xZT5FinOML31CR6t9E/j3dqV6p+G |
|
fdlFLe3IqtC0/bPVnCDBirBygBI4uCrMq+1VhAxPWclrDo7l9QRYbsExH9lfn+Ry |
|
vxeNMZiOASasvVZNncY8E9usBGRdH17EfDL/TPwXqWOLyxSN5o54GTztjjy9w9CG |
|
QP7jcCueKYyQJQCtEmnwc6P/q6/EPv5R6drBkX6loAPtmCUAkHqxkWOJrRq/v7Pw |
|
zRYhfY+ZpVHGc7WEkDnLzRiUypr1C9oxvLKS10etZEIwEdKyOkSg2fdPAgMBAAGj |
|
EzARMA8GA1UdEwEB/wQFMAMCAQAwDQYJKoZIhvcNAQEFBQADggEBAEcz0RTTJ99l |
|
HTK/zTyfV5VZEhtwqu6bwre/hD7lhI+1ji0DZYGIgCbJLKuZhj+cHn2h5nPhN7zE |
|
M9tc4pn0TgeVS0SVFSe6TGnIFipNogvP17E+vXpDZcW/xn9kPKeVCZc1hlDt1W4Z |
|
5q+ub3aUwuMwYs7bcArtDrumCmciJ3LFyNhebPi4mntb5ooeLFLaujEmVYyrQnpo |
|
tWKC9sMlJmLm4yAso64Sv9KLS2T9ivJBNn0ZtougozBCCTqrqgZVjha+B2yjHe9f |
|
sRkg/uxcJf7wC5Y0BLlp1+aPwdmZD87T3a1uQ1Ij93jmHG+2T9U20MklHAePOl0q |
|
yTqdSPnSH1c= |
|
-----END CERTIFICATE----- |
|
`) |
|
keyBytes = []byte(`-----BEGIN RSA PRIVATE KEY----- |
|
MIIEpQIBAAKCAQEA3X94nDbxbK5a5zS4vEqHLHKpUmxavqRL5oXEqKoAy6nm56rv |
|
C3e9xySe+DBlxIEV/MWU+RYpzjC99QkerfRP493aleqfhn3ZRS3tyKrQtP2z1Zwg |
|
wYqwcoASOLgqzKvtVYQMT1nJaw6O5fUEWG7BMR/ZX5/kcr8XjTGYjgEmrL1WTZ3G |
|
PBPbrARkXR9exHwy/0z8F6lji8sUjeaOeBk87Y48vcPQhkD+43ArnimMkCUArRJp |
|
8HOj/6uvxD7+UenawZF+paAD7ZglAJB6sZFjia0av7+z8M0WIX2PmaVRxnO1hJA5 |
|
y80YlMqa9QvaMbyyktdHrWRCMBHSsjpEoNn3TwIDAQABAoIBAQCwgp6YzmgCFce3 |
|
LBpzYmjqEM3CMzr1ZXRe1gbr6d4Mbu7leyBX4SpJAnP0kIzo1X2yG7ol7XWPLOST |
|
2pqqQWFQ00EX6wsJYEy+hmVRXl5HfU3MUkkAMwd9l3Xt4UWqKPBPD5XHvmN2fvl9 |
|
Y4388vXdseXGAGNK1eFs0TMjJuOtDxDyrmJcnxpJ7y/77y/Hb5rUa9DCvj8tkKHg |
|
HmeIwQE0HhIFofj+qCYbqeVyjbPAaYZMrISXb2HmcyULKEOGRbMH24IzInKA0NxV |
|
kdP9qmV8Y2bJ609Fft/y8Vpj31iEdq/OFXyobdVvnXMnaVyAetoaWy7AOTIQ2Cnw |
|
wGbJ/F8BAoGBAN/pCnLQrWREeVMuFjf+MgYgCtRRaQ8EOVvjYcXXi0PhtOMFTAb7 |
|
djqhlgmBOFsmeXcb8YRZsF+pNtu1xk5RJOquyKfK8j1rUdAJfoxGHiaUFI2/1i9E |
|
zuXX/Ao0xNRkWMxMKuwYBmmt1fMuVo+1M8UEwFMdHRtgxe+/+eOV1J2PAoGBAP09 |
|
7GLOYSYAI1OO3BN/bEVNau6tAxP5YShGmX2Qxy0+ooxHZ1V3D8yo6C0hSg+H+fPT |
|
mjMgGcvaW6K+QyCdHDjgbk2hfdZ+Beq92JApPrH9gMV7MPhwHzgwjzDDio9OFxYY |
|
3vjBQ2yX+9jvz9lkvq2NM3fqFqbsG6Et+5mCc6pBAoGBAI62bxVtEgbladrtdfXs |
|
S6ABzkUzOl362EBL9iZuUnJKqstDtgiBQALwuLuIJA5cwHB9W/t6WuMt7CwveJy0 |
|
NW5rRrNDtBAXlgad9o2bp135ZfxO+EoadjCi8B7lMUsaRkq4hWcDjRrQVJxxvXRN |
|
DxkVBSw0Uzf+/0nnN3OqLODbAoGACCY+/isAC1YDzQOS53m5RT2pjEa7C6CB1Ob4 |
|
t4a6MiWK25LMq35qXr6swg8JMBjDHWqY0r5ctievvTv8Mwd7SgVG526j+wwRKq2z |
|
U2hQYS/0Peap+8S37Hn7kakpQ1VS/t4MBttJTSxS6XdGLAvG6xTZLCm3UuXUOcqe |
|
ByGgkUECgYEAmop45kRi974g4MPvyLplcE4syb19ifrHj76gPRBi94Cp8jZosY1T |
|
ucCCa4lOGgPtXJ0Qf1c8yq5vh4yqkQjrgUTkr+CFDGR6y4CxmNDQxEMYIajaIiSY |
|
qmgvgyRayemfO2zR0CPgC6wSoGBth+xW6g+WA8y0z76ZSaWpFi8lVM4= |
|
-----END RSA PRIVATE KEY----- |
|
`) |
|
) |
|
|
|
func pipe() (net.Conn, net.Conn) { |
|
l, err := net.Listen("tcp", "localhost:0") |
|
if err != nil { |
|
log.Fatal(err) |
|
} |
|
defer l.Close() |
|
|
|
client_ch := make(chan net.Conn, 1) |
|
go func() { |
|
client, err := net.Dial(l.Addr().Network(), l.Addr().String()) |
|
if err != nil { |
|
log.Fatal(err) |
|
} |
|
client_ch <- client |
|
}() |
|
|
|
server_conn, err := l.Accept() |
|
if err != nil { |
|
log.Fatal(err) |
|
} |
|
return server_conn, <-client_ch |
|
} |
|
|
|
type HandshakingConn interface { |
|
net.Conn |
|
Handshake() error |
|
} |
|
|
|
func passThruVerify(ok bool, store *openssl.CertificateStoreCtx) bool { |
|
cert := store.GetCurrentCert() |
|
if cert == nil { |
|
log.Fatal("Could not obtain cert from store\n") |
|
} |
|
sn := cert.GetSerialNumberHex() |
|
if len(sn) == 0 { |
|
log.Fatal("Could not obtain serial number from cert") |
|
} |
|
return ok |
|
} |
|
|
|
func opensslWrap(server_conn, client_conn net.Conn) ( |
|
server, client HandshakingConn) { |
|
ctx, err := openssl.NewCtx() |
|
if err != nil { |
|
log.Fatal(err) |
|
} |
|
ctx.SetVerify(openssl.VerifyNone, passThruVerify) |
|
key, err := openssl.LoadPrivateKeyFromPEM(keyBytes) |
|
if err != nil { |
|
log.Fatal(err) |
|
} |
|
err = ctx.UsePrivateKey(key) |
|
if err != nil { |
|
log.Fatal(err) |
|
} |
|
cert, err := openssl.LoadCertificateFromPEM(certBytes) |
|
if err != nil { |
|
log.Fatal(err) |
|
} |
|
err = ctx.UseCertificate(cert) |
|
if err != nil { |
|
log.Fatal(err) |
|
} |
|
err = ctx.SetCipherList("AES128-SHA") |
|
if err != nil { |
|
log.Fatal(err) |
|
} |
|
server, err = openssl.Server(server_conn, ctx) |
|
if err != nil { |
|
log.Fatal(err) |
|
} |
|
client, err = openssl.Client(client_conn, ctx) |
|
if err != nil { |
|
log.Fatal(err) |
|
} |
|
return server, client |
|
} |
|
|
|
func runTest() { |
|
{ |
|
server_conn, client_conn := pipe() |
|
server, client := opensslWrap(server_conn, client_conn) |
|
|
|
var wg sync.WaitGroup |
|
wg.Add(2) |
|
|
|
go func() { |
|
defer wg.Done() |
|
err := client.Handshake() |
|
if err != nil { |
|
log.Fatal(err) |
|
} |
|
}() |
|
|
|
go func() { |
|
defer wg.Done() |
|
err := server.Handshake() |
|
if err != nil { |
|
log.Fatal(err) |
|
} |
|
}() |
|
|
|
wg.Wait() |
|
|
|
if err := server.Close(); err != nil { |
|
log.Fatal(err) |
|
} |
|
|
|
if err := client.Close(); err != nil { |
|
log.Fatal(err) |
|
} |
|
} |
|
|
|
for i := 0; i < 100; i++ { |
|
runtime.GC() |
|
} |
|
} |
|
|
|
func init() { |
|
log.SetFlags(log.LstdFlags | log.Lshortfile) |
|
debug.SetGCPercent(0) |
|
} |
|
|
|
func main() { |
|
runTest() |
|
} |