@ -19,7 +19,6 @@ limitations under the License.
package hsm
import (
"context"
"crypto"
"crypto/ecdsa"
"crypto/rand"
@ -54,25 +53,34 @@ type caFile struct {
label string
}
func ( c * caFile ) buildCertificatePath ( ctx context . Context ) ( string , error ) {
fileName := c . sc . CertificateFileName ( c . label )
type Access struct {
infoLog * log . Logger
caDirectory string
signerConfig * config . SignerConfig
p11Contexts map [ string ] * crypto11 . Context
setupMode bool
verbose bool
}
caDir := ctx . Value ( ctxCADirectory )
func NewAccess ( infoLog * log . Logger , options ... ConfigOption ) ( * Access , error ) {
access := & Access { infoLog : infoLog }
access . setupContext ( options ... )
if caDir != nil {
caPath , ok := caDir . ( string )
if ! ok {
return "" , errors . New ( "context object CA directory is not a string" )
}
return access , nil
}
return path . Join ( caPath , fileName ) , nil
func ( c * caFile ) buildCertificatePath ( caDirectory string ) ( string , error ) {
fileName := c . sc . CertificateFileName ( c . label )
if caDirectory == "" {
return "" , errors . New ( "CA directory is not set" )
}
return fileName , nil
return path. Join ( caDirectory , fileName) , nil
}
func ( c * caFile ) loadCertificate ( c tx context . Context ) ( * x509 . Certificate , error ) {
certFile , err := c . buildCertificatePath ( c tx )
func ( c * caFile ) loadCertificate ( c aDirectory string ) ( * x509 . Certificate , error ) {
certFile , err := c . buildCertificatePath ( c aDirectory )
if err != nil {
return nil , err
}
@ -112,8 +120,8 @@ func (c *caFile) loadCertificate(ctx context.Context) (*x509.Certificate, error)
return certificate , nil
}
func ( c * caFile ) storeCertificate ( c tx context . Context , certificate [ ] byte ) error {
certFile , err := c . buildCertificatePath ( c tx )
func ( c * caFile ) storeCertificate ( c aDirectory string , certificate [ ] byte ) error {
certFile , err := c . buildCertificatePath ( c aDirectory )
if err != nil {
return err
}
@ -126,13 +134,13 @@ func (c *caFile) storeCertificate(ctx context.Context, certificate []byte) error
return nil
}
func GetRootCACertificate ( ctx context . Context , label string ) ( * x509 . Certificate , error ) {
func ( a * Access ) GetRootCACertificate ( label string ) ( * x509 . Certificate , error ) {
var (
certificate * x509 . Certificate
keyPair crypto . Signer
)
sc := GetSignerConfig ( ctx )
sc := a . GetSignerConfig ( )
caCert , err := sc . GetCADefinition ( label )
if err != nil {
@ -145,37 +153,39 @@ func GetRootCACertificate(ctx context.Context, label string) (*x509.Certificate,
caFile := & caFile { sc : sc , label : label }
certificate , err = caFile . loadCertificate ( ctx )
certificate , err = caFile . loadCertificate ( a. caDirectory )
if err != nil {
return nil , err
}
if certificate != nil && ! IsSetupMode ( ctx ) {
if certificate != nil && ! a . IsSetupMode ( ) {
caCert . Certificate = certificate
return certificate , nil
}
keyPair , err = getKeyPair ( ctx , label , caCert . KeyInfo )
keyPair , err = a . getKeyPair ( label , caCert . KeyInfo )
if err != nil {
return nil , err
}
if certificate != nil && certificateMatches ( certificate , keyPair ) {
caCert . Certificate , caCert . KeyPair = certificate , keyPair
if certificate != nil {
err := certificateMatches ( certificate , keyPair )
if err != nil {
return nil , err
}
return certificate , nil
}
if ! IsSetupMode ( ctx ) {
if ! a . IsSetupMode ( ) {
return nil , errCertificateGenerationRefused
}
notBefore , notAfter := sc . CalculateValidity ( caCert , time . Now ( ) )
subject := sc . CalculateSubject ( caCert )
certificate , err = generateRootCACertificate (
ctx ,
certificate , err = a . generateRootCACertificate (
caFile ,
keyPair ,
& x509 . Certificate {
@ -194,7 +204,7 @@ func GetRootCACertificate(ctx context.Context, label string) (*x509.Certificate,
return nil , err
}
p11Context , err := GetP11Context ( ctx , caCert )
p11Context , err := a . GetP11Context ( caCert )
if err != nil {
return nil , err
}
@ -209,13 +219,13 @@ func GetRootCACertificate(ctx context.Context, label string) (*x509.Certificate,
return certificate , nil
}
func GetIntermediaryCACertificate ( ctx context . Context , certLabel string ) ( * x509 . Certificate , error ) {
func ( a * Access ) GetIntermediaryCACertificate ( certLabel string ) ( * x509 . Certificate , error ) {
var (
certificate * x509 . Certificate
keyPair crypto . Signer
)
sc := GetSignerConfig ( ctx )
sc := a . GetSignerConfig ( )
caCert , err := sc . GetCADefinition ( certLabel )
if err != nil {
@ -229,33 +239,35 @@ func GetIntermediaryCACertificate(ctx context.Context, certLabel string) (*x509.
)
}
keyPair , err = getKeyPair ( ctx , certLabel , caCert . KeyInfo )
keyPair , err = a . getKeyPair ( certLabel , caCert . KeyInfo )
if err != nil {
return nil , err
}
certFile := & caFile { sc : sc , label : certLabel }
certificate , err = certFile . loadCertificate ( ctx )
certificate , err = certFile . loadCertificate ( a. caDirectory )
if err != nil {
return nil , err
}
if certificate != nil && certificateMatches ( certificate , keyPair ) {
caCert . Certificate , caCert . KeyPair = certificate , keyPair
if certificate != nil {
err := certificateMatches ( certificate , keyPair )
if err != nil {
return nil , err
}
return certificate , nil
}
if ! IsSetupMode ( ctx ) {
if ! a . IsSetupMode ( ) {
return nil , errCertificateGenerationRefused
}
notBefore , notAfter := sc . CalculateValidity ( caCert , time . Now ( ) )
subject := sc . CalculateSubject ( caCert )
certificate , err = generateIntermediaryCACertificate (
ctx ,
certificate , err = a . generateIntermediaryCACertificate (
certFile ,
sc ,
certLabel ,
@ -284,7 +296,7 @@ func GetIntermediaryCACertificate(ctx context.Context, certLabel string) (*x509.
return nil , err
}
p11Context , err := GetP11Context ( ctx , caCert )
p11Context , err := a . GetP11Context ( caCert )
if err != nil {
return nil , err
}
@ -299,8 +311,7 @@ func GetIntermediaryCACertificate(ctx context.Context, certLabel string) (*x509.
return certificate , nil
}
func generateIntermediaryCACertificate (
ctx context . Context ,
func ( a * Access ) generateIntermediaryCACertificate (
certFile * caFile ,
config * config . SignerConfig ,
certLabel string ,
@ -340,7 +351,7 @@ func generateIntermediaryCACertificate(
Bytes : certBytes ,
}
err = certFile . storeCertificate ( ctx , pem . EncodeToMemory ( certBlock ) )
err = certFile . storeCertificate ( a. caDirectory , pem . EncodeToMemory ( certBlock ) )
if err != nil {
return nil , err
}
@ -367,8 +378,8 @@ func addCertificate(p11Context *crypto11.Context, label string, certificate *x50
return nil
}
func getKeyPair ( ctx context . Context , label string , keyInfo * config . PrivateKeyInfo ) ( crypto . Signer , error ) {
sc := GetSignerConfig ( ctx )
func ( a * Access ) getKeyPair ( label string , keyInfo * config . PrivateKeyInfo ) ( crypto . Signer , error ) {
sc := a . GetSignerConfig ( )
cert , err := sc . GetCADefinition ( label )
if err != nil {
@ -379,7 +390,7 @@ func getKeyPair(ctx context.Context, label string, keyInfo *config.PrivateKeyInf
return cert . KeyPair , nil
}
p11Context , err := GetP11Context ( ctx , cert )
p11Context , err := a . GetP11Context ( cert )
if err != nil {
return nil , err
}
@ -393,7 +404,7 @@ func getKeyPair(ctx context.Context, label string, keyInfo *config.PrivateKeyInf
return keyPair , nil
}
if ! IsSetupMode ( ctx ) {
if ! a . IsSetupMode ( ) {
return nil , errKeyGenerationRefused
}
@ -480,8 +491,7 @@ func randomObjectID() ([]byte, error) {
return result , nil
}
func generateRootCACertificate (
ctx context . Context ,
func ( a * Access ) generateRootCACertificate (
certFile * caFile ,
keyPair crypto . Signer ,
template * x509 . Certificate ,
@ -514,7 +524,7 @@ func generateRootCACertificate(
Bytes : certBytes ,
}
if err = certFile . storeCertificate ( ctx , pem . EncodeToMemory ( certBlock ) ) ; err != nil {
if err = certFile . storeCertificate ( a. caDirectory , pem . EncodeToMemory ( certBlock ) ) ; err != nil {
return nil , err
}
@ -538,31 +548,29 @@ func determineSignatureAlgorithm(keyPair crypto.Signer) (x509.SignatureAlgorithm
}
}
func certificateMatches ( certificate * x509 . Certificate , key crypto . Signer ) bool {
func certificateMatches ( certificate * x509 . Certificate , key crypto . Signer ) error {
switch v := certificate . PublicKey . ( type ) {
case * ecdsa . PublicKey :
if pub , ok := key . Public ( ) . ( * ecdsa . PublicKey ) ; ok {
if v . Equal ( pub ) {
return true
return nil
}
}
case * rsa . PublicKey :
if pub , ok := key . Public ( ) . ( * rsa . PublicKey ) ; ok {
if v . Equal ( pub ) {
return true
return nil
}
}
default :
log . Print f( "unsupported public key %v" , v )
return fmt . Error f( "unsupported public key %v" , v )
}
log . Print f(
return fmt . Error f(
"public key from certificate does not match private key: %s != %s" ,
certificate . PublicKey ,
key . Public ( ) ,
)
return false
}
func randomSerialNumber ( ) ( * big . Int , error ) {