...

Source file src/github.com/sassoftware/relic/token/p11token/rsa.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  	"crypto/rsa"
    22  	"errors"
    23  	"math/big"
    24  
    25  	"github.com/miekg/pkcs11"
    26  	"github.com/sassoftware/relic/lib/x509tools"
    27  )
    28  
    29  // Convert token RSA public key to *rsa.PublicKey
    30  func (key *Key) toRsaKey() (crypto.PublicKey, error) {
    31  	modulus := key.token.getAttribute(key.pub, pkcs11.CKA_MODULUS)
    32  	exponent := key.token.getAttribute(key.pub, pkcs11.CKA_PUBLIC_EXPONENT)
    33  	if len(modulus) == 0 || len(exponent) == 0 {
    34  		return nil, errors.New("Unable to retrieve RSA public key")
    35  	}
    36  	n := new(big.Int).SetBytes([]byte(modulus))
    37  	e := int(attrToInt(exponent))
    38  	return &rsa.PublicKey{N: n, E: e}, nil
    39  }
    40  
    41  func (key *Key) newPssMech(opts *rsa.PSSOptions) (*pkcs11.Mechanism, error) {
    42  	var hashAlg, mgfType uint
    43  	switch opts.Hash {
    44  	case crypto.SHA1:
    45  		hashAlg = pkcs11.CKM_SHA_1
    46  		mgfType = pkcs11.CKG_MGF1_SHA1
    47  	case crypto.SHA224:
    48  		hashAlg = pkcs11.CKM_SHA224
    49  		mgfType = pkcs11.CKG_MGF1_SHA224
    50  	case crypto.SHA256:
    51  		hashAlg = pkcs11.CKM_SHA256
    52  		mgfType = pkcs11.CKG_MGF1_SHA256
    53  	case crypto.SHA384:
    54  		hashAlg = pkcs11.CKM_SHA384
    55  		mgfType = pkcs11.CKG_MGF1_SHA384
    56  	case crypto.SHA512:
    57  		hashAlg = pkcs11.CKM_SHA512
    58  		mgfType = pkcs11.CKG_MGF1_SHA512
    59  	default:
    60  		return nil, errors.New("unsupported hash type for PSS")
    61  	}
    62  	saltLength := opts.SaltLength
    63  	switch saltLength {
    64  	case rsa.PSSSaltLengthAuto:
    65  		pub := key.pubParsed.(*rsa.PublicKey)
    66  		saltLength = (pub.N.BitLen()+7)/8 - 2 - opts.Hash.Size()
    67  	case rsa.PSSSaltLengthEqualsHash:
    68  		saltLength = opts.Hash.Size()
    69  	}
    70  	args := make([]byte, ulongSize*3)
    71  	putUlong(args, hashAlg)
    72  	putUlong(args[ulongSize:], mgfType)
    73  	putUlong(args[ulongSize*2:], uint(saltLength))
    74  	return pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS_PSS, args), nil
    75  }
    76  
    77  // Sign a digest using token RSA private key
    78  func (key *Key) signRSA(digest []byte, opts crypto.SignerOpts) ([]byte, error) {
    79  	var mech *pkcs11.Mechanism
    80  	if opts == nil || opts.HashFunc() == 0 {
    81  		return nil, errors.New("Signer options are required")
    82  	} else if pss, ok := opts.(*rsa.PSSOptions); ok {
    83  		var err error
    84  		mech, err = key.newPssMech(pss)
    85  		if err != nil {
    86  			return nil, err
    87  		}
    88  	} else {
    89  		var ok bool
    90  		digest, ok = x509tools.MarshalDigest(opts.HashFunc(), digest)
    91  		if !ok {
    92  			return nil, errors.New("unsupported hash function")
    93  		}
    94  		mech = pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS, nil)
    95  	}
    96  	err := key.token.ctx.SignInit(key.token.sh, []*pkcs11.Mechanism{mech}, key.priv)
    97  	if err != nil {
    98  		return nil, err
    99  	}
   100  	return key.token.ctx.Sign(key.token.sh, digest)
   101  }
   102  
   103  // Generate RSA-specific public and private key attributes from a PrivateKey
   104  func rsaImportAttrs(priv *rsa.PrivateKey) (pubAttrs, privAttrs []*pkcs11.Attribute, err error) {
   105  	if len(priv.Primes) != 2 || priv.Precomputed.Dp == nil || priv.Precomputed.Dq == nil || priv.Precomputed.Qinv == nil {
   106  		// multi-prime keys and keys without the precomputed values are rare
   107  		// enough not to be interesting
   108  		return nil, nil, errors.New("unsupported RSA key")
   109  	}
   110  	pubAttrs = []*pkcs11.Attribute{
   111  		pkcs11.NewAttribute(pkcs11.CKA_PUBLIC_EXPONENT, big.NewInt(int64(priv.E)).Bytes()),
   112  		pkcs11.NewAttribute(pkcs11.CKA_MODULUS, priv.N.Bytes()),
   113  	}
   114  	privAttrs = []*pkcs11.Attribute{
   115  		pkcs11.NewAttribute(pkcs11.CKA_PUBLIC_EXPONENT, big.NewInt(int64(priv.E)).Bytes()),
   116  		pkcs11.NewAttribute(pkcs11.CKA_MODULUS, priv.N.Bytes()),
   117  		pkcs11.NewAttribute(pkcs11.CKA_PRIVATE_EXPONENT, priv.D.Bytes()),
   118  		pkcs11.NewAttribute(pkcs11.CKA_PRIME_1, priv.Primes[0].Bytes()),
   119  		pkcs11.NewAttribute(pkcs11.CKA_PRIME_2, priv.Primes[1].Bytes()),
   120  		pkcs11.NewAttribute(pkcs11.CKA_EXPONENT_1, priv.Precomputed.Dp.Bytes()),
   121  		pkcs11.NewAttribute(pkcs11.CKA_EXPONENT_2, priv.Precomputed.Dq.Bytes()),
   122  		pkcs11.NewAttribute(pkcs11.CKA_COEFFICIENT, priv.Precomputed.Qinv.Bytes()),
   123  	}
   124  	return
   125  }
   126  
   127  // Generate RSA-specific public attributes to generate an RSA key in the token
   128  func rsaGenerateAttrs(bits uint) ([]*pkcs11.Attribute, *pkcs11.Mechanism, error) {
   129  	if bits < 1024 || bits > 4096 {
   130  		return nil, nil, errors.New("unsupported number of bits")
   131  	}
   132  	pubExponent := []byte{1, 0, 1} // 65537
   133  	attrs := []*pkcs11.Attribute{
   134  		pkcs11.NewAttribute(pkcs11.CKA_MODULUS_BITS, bits),
   135  		pkcs11.NewAttribute(pkcs11.CKA_PUBLIC_EXPONENT, pubExponent),
   136  	}
   137  	mech := pkcs11.NewMechanism(pkcs11.CKM_RSA_X9_31_KEY_PAIR_GEN, nil)
   138  	return attrs, mech, nil
   139  }
   140  

View as plain text