...

Source file src/github.com/ThalesIgnite/crypto11/dsa.go

Documentation: github.com/ThalesIgnite/crypto11

     1  // Copyright 2016, 2017 Thales e-Security, Inc
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining
     4  // a copy of this software and associated documentation files (the
     5  // "Software"), to deal in the Software without restriction, including
     6  // without limitation the rights to use, copy, modify, merge, publish,
     7  // distribute, sublicense, and/or sell copies of the Software, and to
     8  // permit persons to whom the Software is furnished to do so, subject to
     9  // the following conditions:
    10  //
    11  // The above copyright notice and this permission notice shall be
    12  // included in all copies or substantial portions of the Software.
    13  //
    14  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    15  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    16  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    17  // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    18  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    19  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    20  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    21  
    22  package crypto11
    23  
    24  import (
    25  	"crypto"
    26  	"crypto/dsa"
    27  	"io"
    28  	"math/big"
    29  
    30  	"github.com/pkg/errors"
    31  
    32  	pkcs11 "github.com/miekg/pkcs11"
    33  )
    34  
    35  // pkcs11PrivateKeyDSA contains a reference to a loaded PKCS#11 DSA private key object.
    36  type pkcs11PrivateKeyDSA struct {
    37  	pkcs11PrivateKey
    38  }
    39  
    40  // Export the public key corresponding to a private DSA key.
    41  func exportDSAPublicKey(session *pkcs11Session, pubHandle pkcs11.ObjectHandle) (crypto.PublicKey, error) {
    42  	template := []*pkcs11.Attribute{
    43  		pkcs11.NewAttribute(pkcs11.CKA_PRIME, nil),
    44  		pkcs11.NewAttribute(pkcs11.CKA_SUBPRIME, nil),
    45  		pkcs11.NewAttribute(pkcs11.CKA_BASE, nil),
    46  		pkcs11.NewAttribute(pkcs11.CKA_VALUE, nil),
    47  	}
    48  	exported, err := session.ctx.GetAttributeValue(session.handle, pubHandle, template)
    49  	if err != nil {
    50  		return nil, err
    51  	}
    52  	var p, q, g, y big.Int
    53  	p.SetBytes(exported[0].Value)
    54  	q.SetBytes(exported[1].Value)
    55  	g.SetBytes(exported[2].Value)
    56  	y.SetBytes(exported[3].Value)
    57  	result := dsa.PublicKey{
    58  		Parameters: dsa.Parameters{
    59  			P: &p,
    60  			Q: &q,
    61  			G: &g,
    62  		},
    63  		Y: &y,
    64  	}
    65  	return &result, nil
    66  }
    67  
    68  func notNilBytes(obj []byte, name string) error {
    69  	if obj == nil {
    70  		return errors.Errorf("%s cannot be nil", name)
    71  	}
    72  	return nil
    73  }
    74  
    75  // GenerateDSAKeyPair creates a DSA key pair on the token. The id parameter is used to
    76  // set CKA_ID and must be non-nil.
    77  func (c *Context) GenerateDSAKeyPair(id []byte, params *dsa.Parameters) (Signer, error) {
    78  	if c.closed.Get() {
    79  		return nil, errClosed
    80  	}
    81  
    82  	public, err := NewAttributeSetWithID(id)
    83  	if err != nil {
    84  		return nil, err
    85  	}
    86  	// Copy the AttributeSet to allow modifications.
    87  	private := public.Copy()
    88  
    89  	return c.GenerateDSAKeyPairWithAttributes(public, private, params)
    90  }
    91  
    92  // GenerateDSAKeyPairWithLabel creates a DSA key pair on the token. The id and label parameters are used to
    93  // set CKA_ID and CKA_LABEL respectively and must be non-nil.
    94  func (c *Context) GenerateDSAKeyPairWithLabel(id, label []byte, params *dsa.Parameters) (Signer, error) {
    95  	if c.closed.Get() {
    96  		return nil, errClosed
    97  	}
    98  
    99  	public, err := NewAttributeSetWithIDAndLabel(id, label)
   100  	if err != nil {
   101  		return nil, err
   102  	}
   103  	// Copy the AttributeSet to allow modifications.
   104  	private := public.Copy()
   105  
   106  	return c.GenerateDSAKeyPairWithAttributes(public, private, params)
   107  }
   108  
   109  // GenerateDSAKeyPairWithAttributes creates a DSA key pair on the token. After this function returns, public and private
   110  // will contain the attributes applied to the key pair. If required attributes are missing, they will be set to a
   111  // default value.
   112  func (c *Context) GenerateDSAKeyPairWithAttributes(public, private AttributeSet, params *dsa.Parameters) (Signer, error) {
   113  	if c.closed.Get() {
   114  		return nil, errClosed
   115  	}
   116  
   117  	var k Signer
   118  	err := c.withSession(func(session *pkcs11Session) error {
   119  		p := params.P.Bytes()
   120  		q := params.Q.Bytes()
   121  		g := params.G.Bytes()
   122  
   123  		public.AddIfNotPresent([]*pkcs11.Attribute{
   124  			pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PUBLIC_KEY),
   125  			pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_DSA),
   126  			pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
   127  			pkcs11.NewAttribute(pkcs11.CKA_VERIFY, true),
   128  			pkcs11.NewAttribute(pkcs11.CKA_PRIME, p),
   129  			pkcs11.NewAttribute(pkcs11.CKA_SUBPRIME, q),
   130  			pkcs11.NewAttribute(pkcs11.CKA_BASE, g),
   131  		})
   132  		private.AddIfNotPresent([]*pkcs11.Attribute{
   133  			pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
   134  			pkcs11.NewAttribute(pkcs11.CKA_SIGN, true),
   135  			pkcs11.NewAttribute(pkcs11.CKA_SENSITIVE, true),
   136  			pkcs11.NewAttribute(pkcs11.CKA_EXTRACTABLE, false),
   137  		})
   138  
   139  		mech := []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_DSA_KEY_PAIR_GEN, nil)}
   140  		pubHandle, privHandle, err := session.ctx.GenerateKeyPair(session.handle,
   141  			mech,
   142  			public.ToSlice(),
   143  			private.ToSlice())
   144  		if err != nil {
   145  			return err
   146  		}
   147  		pub, err := exportDSAPublicKey(session, pubHandle)
   148  		if err != nil {
   149  			return err
   150  		}
   151  		k = &pkcs11PrivateKeyDSA{
   152  			pkcs11PrivateKey: pkcs11PrivateKey{
   153  				pkcs11Object: pkcs11Object{
   154  					handle:  privHandle,
   155  					context: c,
   156  				},
   157  				pubKeyHandle: pubHandle,
   158  				pubKey:       pub,
   159  			}}
   160  		return nil
   161  
   162  	})
   163  	return k, err
   164  }
   165  
   166  // Sign signs a message using a DSA key.
   167  //
   168  // This completes the implemention of crypto.Signer for pkcs11PrivateKeyDSA.
   169  //
   170  // PKCS#11 expects to pick its own random data for signatures, so the rand argument is ignored.
   171  //
   172  // The return value is a DER-encoded byteblock.
   173  func (signer *pkcs11PrivateKeyDSA) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) (signature []byte, err error) {
   174  	return signer.context.dsaGeneric(signer.handle, pkcs11.CKM_DSA, digest)
   175  }
   176  

View as plain text