...

Source file src/github.com/sassoftware/relic/token/p11token/key.go

Documentation: github.com/sassoftware/relic/token/p11token

     1  //
     2  // Copyright (c) SAS Institute Inc.
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //     http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  // Unless required by applicable law or agreed to in writing, software
    11  // distributed under the License is distributed on an "AS IS" BASIS,
    12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  //
    16  
    17  package p11token
    18  
    19  import (
    20  	"crypto"
    21  	"errors"
    22  	"io"
    23  
    24  	"github.com/miekg/pkcs11"
    25  	"github.com/sassoftware/relic/config"
    26  	"github.com/sassoftware/relic/signers/sigerrors"
    27  	"github.com/sassoftware/relic/token"
    28  )
    29  
    30  type Key struct {
    31  	PgpCertificate  string
    32  	X509Certificate string
    33  	token           *Token
    34  	keyConf         *config.KeyConfig
    35  	keyType         uint
    36  	pub             pkcs11.ObjectHandle
    37  	priv            pkcs11.ObjectHandle
    38  	pubParsed       crypto.PublicKey
    39  }
    40  
    41  func (token *Token) GetKey(keyName string) (token.Key, error) {
    42  	token.mutex.Lock()
    43  	defer token.mutex.Unlock()
    44  	keyConf, err := token.config.GetKey(keyName)
    45  	if err != nil {
    46  		return nil, err
    47  	}
    48  	return token.getKey(keyConf, keyName)
    49  }
    50  
    51  func (token *Token) getKey(keyConf *config.KeyConfig, keyName string) (*Key, error) {
    52  	var err error
    53  	key := &Key{
    54  		token:           token,
    55  		keyConf:         keyConf,
    56  		PgpCertificate:  keyConf.PgpCertificate,
    57  		X509Certificate: keyConf.X509Certificate,
    58  	}
    59  	key.priv, err = token.findKey(keyConf, pkcs11.CKO_PRIVATE_KEY)
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  	key.pub, err = token.findKey(keyConf, pkcs11.CKO_PUBLIC_KEY)
    64  	if err != nil {
    65  		return nil, err
    66  	}
    67  	keyTypeBlob := token.getAttribute(key.priv, pkcs11.CKA_KEY_TYPE)
    68  	if len(keyTypeBlob) == 0 {
    69  		return nil, errors.New("Missing CKA_KEY_TYPE on private key")
    70  	}
    71  	key.keyType = attrToInt(keyTypeBlob)
    72  	switch key.keyType {
    73  	case CKK_RSA:
    74  		key.pubParsed, err = key.toRsaKey()
    75  	case CKK_ECDSA:
    76  		key.pubParsed, err = key.toEcdsaKey()
    77  	default:
    78  		return nil, errors.New("Unsupported key type")
    79  	}
    80  	if err != nil {
    81  		return nil, err
    82  	}
    83  	return key, nil
    84  }
    85  
    86  func (token *Token) findKey(keyConf *config.KeyConfig, class uint) (pkcs11.ObjectHandle, error) {
    87  	attrs := []*pkcs11.Attribute{
    88  		pkcs11.NewAttribute(pkcs11.CKA_CLASS, class),
    89  	}
    90  	if keyConf.Label != "" {
    91  		attrs = append(attrs, pkcs11.NewAttribute(pkcs11.CKA_LABEL, keyConf.Label))
    92  	}
    93  	if keyConf.ID != "" {
    94  		keyID, err := parseKeyID(keyConf.ID)
    95  		if err != nil {
    96  			return 0, err
    97  		}
    98  		attrs = append(attrs, pkcs11.NewAttribute(pkcs11.CKA_ID, keyID))
    99  	}
   100  	objects, err := token.findObject(attrs)
   101  	if err != nil {
   102  		return 0, err
   103  	} else if len(objects) > 1 {
   104  		return 0, errors.New("Multiple token objects with the specified attributes")
   105  	} else if len(objects) == 0 {
   106  		return 0, sigerrors.KeyNotFoundError{}
   107  	}
   108  	return objects[0], nil
   109  }
   110  
   111  func (key *Key) Config() *config.KeyConfig {
   112  	return key.keyConf
   113  }
   114  
   115  func (key *Key) Public() crypto.PublicKey {
   116  	return key.pubParsed
   117  }
   118  
   119  func (key *Key) getLabel() string {
   120  	key.token.mutex.Lock()
   121  	defer key.token.mutex.Unlock()
   122  	return string(key.token.getAttribute(key.priv, pkcs11.CKA_LABEL))
   123  }
   124  
   125  func (key *Key) GetID() []byte {
   126  	key.token.mutex.Lock()
   127  	defer key.token.mutex.Unlock()
   128  	return key.token.getAttribute(key.priv, pkcs11.CKA_ID)
   129  }
   130  
   131  func (key *Key) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) {
   132  	key.token.mutex.Lock()
   133  	defer key.token.mutex.Unlock()
   134  	switch key.keyType {
   135  	case CKK_RSA:
   136  		return key.signRSA(digest, opts)
   137  	case CKK_ECDSA:
   138  		return key.signECDSA(digest)
   139  	default:
   140  		return nil, errors.New("Unsupported key type")
   141  	}
   142  }
   143  

View as plain text