...

Source file src/github.com/ThalesIgnite/crypto11/rsa.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/rsa"
    27  	"errors"
    28  	"io"
    29  	"math/big"
    30  
    31  	"github.com/miekg/pkcs11"
    32  )
    33  
    34  // errMalformedRSAPublicKey is returned when an RSA public key is not in a suitable form.
    35  //
    36  // Currently this means that the public exponent is either bigger than
    37  // 32 bits, or less than 2.
    38  var errMalformedRSAPublicKey = errors.New("malformed RSA public key")
    39  
    40  // errUnsupportedRSAOptions is returned when an unsupported RSA option is requested.
    41  //
    42  // Currently this means a nontrivial SessionKeyLen when decrypting; or
    43  // an unsupported hash function; or crypto.rsa.PSSSaltLengthAuto was
    44  // requested.
    45  var errUnsupportedRSAOptions = errors.New("unsupported RSA option value")
    46  
    47  // pkcs11PrivateKeyRSA contains a reference to a loaded PKCS#11 RSA private key object.
    48  type pkcs11PrivateKeyRSA struct {
    49  	pkcs11PrivateKey
    50  }
    51  
    52  // Export the public key corresponding to a private RSA key.
    53  func exportRSAPublicKey(session *pkcs11Session, pubHandle pkcs11.ObjectHandle) (crypto.PublicKey, error) {
    54  	template := []*pkcs11.Attribute{
    55  		pkcs11.NewAttribute(pkcs11.CKA_MODULUS, nil),
    56  		pkcs11.NewAttribute(pkcs11.CKA_PUBLIC_EXPONENT, nil),
    57  	}
    58  	exported, err := session.ctx.GetAttributeValue(session.handle, pubHandle, template)
    59  	if err != nil {
    60  		return nil, err
    61  	}
    62  	var modulus = new(big.Int)
    63  	modulus.SetBytes(exported[0].Value)
    64  	var bigExponent = new(big.Int)
    65  	bigExponent.SetBytes(exported[1].Value)
    66  	if bigExponent.BitLen() > 32 {
    67  		return nil, errMalformedRSAPublicKey
    68  	}
    69  	if bigExponent.Sign() < 1 {
    70  		return nil, errMalformedRSAPublicKey
    71  	}
    72  	exponent := int(bigExponent.Uint64())
    73  	result := rsa.PublicKey{
    74  		N: modulus,
    75  		E: exponent,
    76  	}
    77  	if result.E < 2 {
    78  		return nil, errMalformedRSAPublicKey
    79  	}
    80  	return &result, nil
    81  }
    82  
    83  // GenerateRSAKeyPair creates an RSA key pair on the token. The id parameter is used to
    84  // set CKA_ID and must be non-nil. RSA private keys are generated with both sign and decrypt
    85  // permissions, and a public exponent of 65537.
    86  func (c *Context) GenerateRSAKeyPair(id []byte, bits int) (SignerDecrypter, error) {
    87  	if c.closed.Get() {
    88  		return nil, errClosed
    89  	}
    90  
    91  	public, err := NewAttributeSetWithID(id)
    92  	if err != nil {
    93  		return nil, err
    94  	}
    95  	// Copy the AttributeSet to allow modifications.
    96  	private := public.Copy()
    97  
    98  	return c.GenerateRSAKeyPairWithAttributes(public, private, bits)
    99  }
   100  
   101  // GenerateRSAKeyPairWithLabel creates an RSA key pair on the token. The id and label parameters are used to
   102  // set CKA_ID and CKA_LABEL respectively and must be non-nil. RSA private keys are generated with both sign and decrypt
   103  // permissions, and a public exponent of 65537.
   104  func (c *Context) GenerateRSAKeyPairWithLabel(id, label []byte, bits int) (SignerDecrypter, error) {
   105  	if c.closed.Get() {
   106  		return nil, errClosed
   107  	}
   108  
   109  	public, err := NewAttributeSetWithIDAndLabel(id, label)
   110  	if err != nil {
   111  		return nil, err
   112  	}
   113  	// Copy the AttributeSet to allow modifications.
   114  	private := public.Copy()
   115  
   116  	return c.GenerateRSAKeyPairWithAttributes(public, private, bits)
   117  }
   118  
   119  // GenerateRSAKeyPairWithAttributes generates an RSA key pair on the token. After this function returns, public and
   120  // private will contain the attributes applied to the key pair. If required attributes are missing, they will be set to
   121  // a default value.
   122  func (c *Context) GenerateRSAKeyPairWithAttributes(public, private AttributeSet, bits int) (SignerDecrypter, error) {
   123  	if c.closed.Get() {
   124  		return nil, errClosed
   125  	}
   126  
   127  	var k SignerDecrypter
   128  
   129  	err := c.withSession(func(session *pkcs11Session) error {
   130  
   131  		public.AddIfNotPresent([]*pkcs11.Attribute{
   132  			pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PUBLIC_KEY),
   133  			pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_RSA),
   134  			pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
   135  			pkcs11.NewAttribute(pkcs11.CKA_VERIFY, true),
   136  			pkcs11.NewAttribute(pkcs11.CKA_ENCRYPT, true),
   137  			pkcs11.NewAttribute(pkcs11.CKA_PUBLIC_EXPONENT, []byte{1, 0, 1}),
   138  			pkcs11.NewAttribute(pkcs11.CKA_MODULUS_BITS, bits),
   139  		})
   140  		private.AddIfNotPresent([]*pkcs11.Attribute{
   141  			pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
   142  			pkcs11.NewAttribute(pkcs11.CKA_SIGN, true),
   143  			pkcs11.NewAttribute(pkcs11.CKA_DECRYPT, true),
   144  			pkcs11.NewAttribute(pkcs11.CKA_SENSITIVE, true),
   145  			pkcs11.NewAttribute(pkcs11.CKA_EXTRACTABLE, false),
   146  		})
   147  
   148  		mech := []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS_KEY_PAIR_GEN, nil)}
   149  		pubHandle, privHandle, err := session.ctx.GenerateKeyPair(session.handle,
   150  			mech,
   151  			public.ToSlice(),
   152  			private.ToSlice())
   153  		if err != nil {
   154  			return err
   155  		}
   156  
   157  		pub, err := exportRSAPublicKey(session, pubHandle)
   158  		if err != nil {
   159  			return err
   160  		}
   161  		k = &pkcs11PrivateKeyRSA{
   162  			pkcs11PrivateKey: pkcs11PrivateKey{
   163  				pkcs11Object: pkcs11Object{
   164  					handle:  privHandle,
   165  					context: c,
   166  				},
   167  				pubKeyHandle: pubHandle,
   168  				pubKey:       pub,
   169  			}}
   170  		return nil
   171  	})
   172  	return k, err
   173  }
   174  
   175  // Decrypt decrypts a message using a RSA key.
   176  //
   177  // This completes the implemention of crypto.Decrypter for pkcs11PrivateKeyRSA.
   178  //
   179  // Note that the SessionKeyLen option (for PKCS#1v1.5 decryption) is not supported.
   180  //
   181  // The underlying PKCS#11 implementation may impose further restrictions.
   182  func (priv *pkcs11PrivateKeyRSA) Decrypt(rand io.Reader, ciphertext []byte, options crypto.DecrypterOpts) (plaintext []byte, err error) {
   183  	err = priv.context.withSession(func(session *pkcs11Session) error {
   184  		if options == nil {
   185  			plaintext, err = decryptPKCS1v15(session, priv, ciphertext, 0)
   186  		} else {
   187  			switch o := options.(type) {
   188  			case *rsa.PKCS1v15DecryptOptions:
   189  				plaintext, err = decryptPKCS1v15(session, priv, ciphertext, o.SessionKeyLen)
   190  			case *rsa.OAEPOptions:
   191  				plaintext, err = decryptOAEP(session, priv, ciphertext, o.Hash, o.Label)
   192  			default:
   193  				err = errUnsupportedRSAOptions
   194  			}
   195  		}
   196  		return err
   197  	})
   198  	return plaintext, err
   199  }
   200  
   201  func decryptPKCS1v15(session *pkcs11Session, key *pkcs11PrivateKeyRSA, ciphertext []byte, sessionKeyLen int) ([]byte, error) {
   202  	if sessionKeyLen != 0 {
   203  		return nil, errUnsupportedRSAOptions
   204  	}
   205  	mech := []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS, nil)}
   206  	if err := session.ctx.DecryptInit(session.handle, mech, key.handle); err != nil {
   207  		return nil, err
   208  	}
   209  	return session.ctx.Decrypt(session.handle, ciphertext)
   210  }
   211  
   212  func decryptOAEP(session *pkcs11Session, key *pkcs11PrivateKeyRSA, ciphertext []byte, hashFunction crypto.Hash,
   213  	label []byte) ([]byte, error) {
   214  
   215  	hashAlg, mgfAlg, _, err := hashToPKCS11(hashFunction)
   216  	if err != nil {
   217  		return nil, err
   218  	}
   219  
   220  	mech := pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS_OAEP,
   221  		pkcs11.NewOAEPParams(hashAlg, mgfAlg, pkcs11.CKZ_DATA_SPECIFIED, label))
   222  
   223  	err = session.ctx.DecryptInit(session.handle, []*pkcs11.Mechanism{mech}, key.handle)
   224  	if err != nil {
   225  		return nil, err
   226  	}
   227  	return session.ctx.Decrypt(session.handle, ciphertext)
   228  }
   229  
   230  func hashToPKCS11(hashFunction crypto.Hash) (hashAlg uint, mgfAlg uint, hashLen uint, err error) {
   231  	switch hashFunction {
   232  	case crypto.SHA1:
   233  		return pkcs11.CKM_SHA_1, pkcs11.CKG_MGF1_SHA1, 20, nil
   234  	case crypto.SHA224:
   235  		return pkcs11.CKM_SHA224, pkcs11.CKG_MGF1_SHA224, 28, nil
   236  	case crypto.SHA256:
   237  		return pkcs11.CKM_SHA256, pkcs11.CKG_MGF1_SHA256, 32, nil
   238  	case crypto.SHA384:
   239  		return pkcs11.CKM_SHA384, pkcs11.CKG_MGF1_SHA384, 48, nil
   240  	case crypto.SHA512:
   241  		return pkcs11.CKM_SHA512, pkcs11.CKG_MGF1_SHA512, 64, nil
   242  	default:
   243  		return 0, 0, 0, errUnsupportedRSAOptions
   244  	}
   245  }
   246  
   247  func signPSS(session *pkcs11Session, key *pkcs11PrivateKeyRSA, digest []byte, opts *rsa.PSSOptions) ([]byte, error) {
   248  	var hMech, mgf, hLen, sLen uint
   249  	var err error
   250  	if hMech, mgf, hLen, err = hashToPKCS11(opts.Hash); err != nil {
   251  		return nil, err
   252  	}
   253  	switch opts.SaltLength {
   254  	case rsa.PSSSaltLengthAuto: // parseltongue constant
   255  		// TODO we could (in principle) work out the biggest
   256  		// possible size from the key, but until someone has
   257  		// the effort to do that...
   258  		return nil, errUnsupportedRSAOptions
   259  	case rsa.PSSSaltLengthEqualsHash:
   260  		sLen = hLen
   261  	default:
   262  		sLen = uint(opts.SaltLength)
   263  	}
   264  	// TODO this is pretty horrible, maybe the PKCS#11 wrapper
   265  	// could be improved to help us out here
   266  	parameters := concat(ulongToBytes(hMech),
   267  		ulongToBytes(mgf),
   268  		ulongToBytes(sLen))
   269  	mech := []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS_PSS, parameters)}
   270  	if err = session.ctx.SignInit(session.handle, mech, key.handle); err != nil {
   271  		return nil, err
   272  	}
   273  	return session.ctx.Sign(session.handle, digest)
   274  }
   275  
   276  var pkcs1Prefix = map[crypto.Hash][]byte{
   277  	crypto.SHA1:   {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14},
   278  	crypto.SHA224: {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c},
   279  	crypto.SHA256: {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20},
   280  	crypto.SHA384: {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30},
   281  	crypto.SHA512: {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40},
   282  }
   283  
   284  func signPKCS1v15(session *pkcs11Session, key *pkcs11PrivateKeyRSA, digest []byte, hash crypto.Hash) (signature []byte, err error) {
   285  	/* Calculate T for EMSA-PKCS1-v1_5. */
   286  	oid := pkcs1Prefix[hash]
   287  	T := make([]byte, len(oid)+len(digest))
   288  	copy(T[0:len(oid)], oid)
   289  	copy(T[len(oid):], digest)
   290  	mech := []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS, nil)}
   291  	err = session.ctx.SignInit(session.handle, mech, key.handle)
   292  	if err == nil {
   293  		signature, err = session.ctx.Sign(session.handle, T)
   294  	}
   295  	return
   296  }
   297  
   298  // Sign signs a message using a RSA key.
   299  //
   300  // This completes the implemention of crypto.Signer for pkcs11PrivateKeyRSA.
   301  //
   302  // PKCS#11 expects to pick its own random data where necessary for signatures, so the rand argument is ignored.
   303  //
   304  // Note that (at present) the crypto.rsa.PSSSaltLengthAuto option is
   305  // not supported. The caller must either use
   306  // crypto.rsa.PSSSaltLengthEqualsHash (recommended) or pass an
   307  // explicit salt length. Moreover the underlying PKCS#11
   308  // implementation may impose further restrictions.
   309  func (priv *pkcs11PrivateKeyRSA) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) (signature []byte, err error) {
   310  	err = priv.context.withSession(func(session *pkcs11Session) error {
   311  		switch opts.(type) {
   312  		case *rsa.PSSOptions:
   313  			signature, err = signPSS(session, priv, digest, opts.(*rsa.PSSOptions))
   314  		default: /* PKCS1-v1_5 */
   315  			signature, err = signPKCS1v15(session, priv, digest, opts.HashFunc())
   316  		}
   317  		return err
   318  	})
   319  
   320  	if err != nil {
   321  		return nil, err
   322  	}
   323  
   324  	return signature, err
   325  }
   326  

View as plain text