6463b87ebe
* add errcheck * fixed linter errors * fixes * errcheck fixes in pkg/paths * Fix errchecks in PieceID.Derive * Fix ecclient tests * Move closeConn a little bit above in the exectution flow * fix new lint errors * Fatalf -> Printf * address eclipsed errors * rename err to closeErr * rename err to closeErr for differentiation
175 lines
3.9 KiB
Go
175 lines
3.9 KiB
Go
// Copyright (C) 2018 Storj Labs, Inc.
|
|
// See LICENSE for copying information.
|
|
|
|
package peertls
|
|
|
|
// Many cryptography standards use ASN.1 to define their data structures,
|
|
// and Distinguished Encoding Rules (DER) to serialize those structures.
|
|
// Because DER produces binary output, it can be challenging to transmit
|
|
// the resulting files through systems, like electronic mail, that only
|
|
// support ASCII. The PEM format solves this problem by encoding the
|
|
// binary data using base64.
|
|
// (see https://en.wikipedia.org/wiki/Privacy-enhanced_Electronic_Mail)
|
|
|
|
import (
|
|
"crypto/ecdsa"
|
|
"crypto/elliptic"
|
|
"crypto/rand"
|
|
"crypto/tls"
|
|
"crypto/x509"
|
|
"io/ioutil"
|
|
"math/big"
|
|
"time"
|
|
|
|
"github.com/zeebo/errs"
|
|
)
|
|
|
|
const (
|
|
// OneYear is the integer represtentation of a calendar year
|
|
OneYear = 365 * 24 * time.Hour
|
|
)
|
|
|
|
func (t *TLSFileOptions) generateTLS() error {
|
|
if err := t.EnsureAbsPaths(); err != nil {
|
|
return ErrGenerate.Wrap(err)
|
|
}
|
|
|
|
rootKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
|
if err != nil {
|
|
return ErrGenerate.New("failed to generateServerTLS root private key", err)
|
|
}
|
|
|
|
rootT, err := rootTemplate(t)
|
|
if err != nil {
|
|
return ErrGenerate.Wrap(err)
|
|
}
|
|
|
|
rootC, err := createAndWrite(
|
|
t.RootCertAbsPath,
|
|
t.RootKeyAbsPath,
|
|
rootT,
|
|
rootT,
|
|
nil,
|
|
&rootKey.PublicKey,
|
|
rootKey,
|
|
rootKey,
|
|
)
|
|
if err != nil {
|
|
return ErrGenerate.Wrap(err)
|
|
}
|
|
|
|
newKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
|
if err != nil {
|
|
return ErrGenerate.New("failed to generateTLS client private key", err)
|
|
}
|
|
|
|
leafT, err := leafTemplate(t)
|
|
if err != nil {
|
|
return ErrGenerate.Wrap(err)
|
|
}
|
|
|
|
leafC, err := createAndWrite(
|
|
t.LeafCertAbsPath,
|
|
t.LeafKeyAbsPath,
|
|
leafT,
|
|
rootT,
|
|
rootC.Certificate,
|
|
&newKey.PublicKey,
|
|
rootKey,
|
|
newKey,
|
|
)
|
|
|
|
if err != nil {
|
|
return ErrGenerate.Wrap(err)
|
|
}
|
|
|
|
t.LeafCertificate = leafC
|
|
|
|
return nil
|
|
}
|
|
|
|
// LoadCert reads and parses a cert/privkey pair from a pair
|
|
// of files. The files must contain PEM encoded data. The certificate file
|
|
// may contain intermediate certificates following the leaf certificate to
|
|
// form a certificate chain. On successful return, Certificate.Leaf will
|
|
// be nil because the parsed form of the certificate is not retained.
|
|
func LoadCert(certFile, keyFile string) (*tls.Certificate, error) {
|
|
certPEMBytes, err := ioutil.ReadFile(certFile)
|
|
if err != nil {
|
|
return &tls.Certificate{}, err
|
|
}
|
|
keyPEMBytes, err := ioutil.ReadFile(keyFile)
|
|
if err != nil {
|
|
return &tls.Certificate{}, err
|
|
}
|
|
|
|
return certFromPEMs(certPEMBytes, keyPEMBytes)
|
|
}
|
|
|
|
func createAndWrite(
|
|
certPath,
|
|
keyPath string,
|
|
template,
|
|
parentTemplate *x509.Certificate,
|
|
parentDERCerts [][]byte,
|
|
pubKey *ecdsa.PublicKey,
|
|
rootKey,
|
|
privKey *ecdsa.PrivateKey) (*tls.Certificate, error) {
|
|
|
|
DERCerts, keyDERBytes, err := createDERs(
|
|
template,
|
|
parentTemplate,
|
|
parentDERCerts,
|
|
pubKey,
|
|
rootKey,
|
|
privKey,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := writeCerts(DERCerts, certPath); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := writeKey(privKey, keyPath); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return certFromDERs(DERCerts, keyDERBytes)
|
|
}
|
|
|
|
func createDERs(
|
|
template,
|
|
parentTemplate *x509.Certificate,
|
|
parentDERCerts [][]byte,
|
|
pubKey *ecdsa.PublicKey,
|
|
rootKey,
|
|
privKey *ecdsa.PrivateKey) (_ [][]byte, _ []byte, _ error) {
|
|
certDERBytes, err := x509.CreateCertificate(rand.Reader, template, parentTemplate, pubKey, rootKey)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
DERCerts := [][]byte{}
|
|
DERCerts = append(DERCerts, certDERBytes)
|
|
DERCerts = append(DERCerts, parentDERCerts...)
|
|
|
|
keyDERBytes, err := keyToDERBytes(privKey)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
return DERCerts, keyDERBytes, nil
|
|
}
|
|
|
|
func newSerialNumber() (*big.Int, error) {
|
|
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
|
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
|
|
if err != nil {
|
|
return nil, errs.New("failed to generateServerTls serial number: %s", err.Error())
|
|
}
|
|
|
|
return serialNumber, nil
|
|
}
|