...

Source file src/github.com/letsencrypt/boulder/cmd/ceremony/rsa.go

Documentation: github.com/letsencrypt/boulder/cmd/ceremony

     1  package main
     2  
     3  import (
     4  	"crypto/rsa"
     5  	"errors"
     6  	"log"
     7  	"math/big"
     8  
     9  	"github.com/letsencrypt/boulder/pkcs11helpers"
    10  	"github.com/miekg/pkcs11"
    11  )
    12  
    13  const (
    14  	rsaExp = 65537
    15  )
    16  
    17  // rsaArgs constructs the private and public key template attributes sent to the
    18  // device and specifies which mechanism should be used. modulusLen specifies the
    19  // length of the modulus to be generated on the device in bits and exponent
    20  // specifies the public exponent that should be used.
    21  func rsaArgs(label string, modulusLen, exponent uint, keyID []byte) generateArgs {
    22  	// Encode as unpadded big endian encoded byte slice
    23  	expSlice := big.NewInt(int64(exponent)).Bytes()
    24  	log.Printf("\tEncoded public exponent (%d) as: %0X\n", exponent, expSlice)
    25  	return generateArgs{
    26  		mechanism: []*pkcs11.Mechanism{
    27  			pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS_KEY_PAIR_GEN, nil),
    28  		},
    29  		publicAttrs: []*pkcs11.Attribute{
    30  			pkcs11.NewAttribute(pkcs11.CKA_ID, keyID),
    31  			pkcs11.NewAttribute(pkcs11.CKA_LABEL, label),
    32  			pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
    33  			// Allow the key to verify signatures
    34  			pkcs11.NewAttribute(pkcs11.CKA_VERIFY, true),
    35  			// Set requested modulus length
    36  			pkcs11.NewAttribute(pkcs11.CKA_MODULUS_BITS, modulusLen),
    37  			// Set requested public exponent
    38  			pkcs11.NewAttribute(pkcs11.CKA_PUBLIC_EXPONENT, expSlice),
    39  		},
    40  		privateAttrs: []*pkcs11.Attribute{
    41  			pkcs11.NewAttribute(pkcs11.CKA_ID, keyID),
    42  			pkcs11.NewAttribute(pkcs11.CKA_LABEL, label),
    43  			pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
    44  			// Prevent attributes being retrieved
    45  			pkcs11.NewAttribute(pkcs11.CKA_SENSITIVE, true),
    46  			// Prevent the key being extracted from the device
    47  			pkcs11.NewAttribute(pkcs11.CKA_EXTRACTABLE, false),
    48  			// Allow the key to create signatures
    49  			pkcs11.NewAttribute(pkcs11.CKA_SIGN, true),
    50  		},
    51  	}
    52  }
    53  
    54  // rsaPub extracts the generated public key, specified by the provided object
    55  // handle, and constructs a rsa.PublicKey. It also checks that the key has the
    56  // correct length modulus and that the public exponent is what was requested in
    57  // the public key template.
    58  func rsaPub(session *pkcs11helpers.Session, object pkcs11.ObjectHandle, modulusLen, exponent uint) (*rsa.PublicKey, error) {
    59  	pubKey, err := session.GetRSAPublicKey(object)
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  	if pubKey.E != int(exponent) {
    64  		return nil, errors.New("returned CKA_PUBLIC_EXPONENT doesn't match expected exponent")
    65  	}
    66  	if pubKey.N.BitLen() != int(modulusLen) {
    67  		return nil, errors.New("returned CKA_MODULUS isn't of the expected bit length")
    68  	}
    69  	log.Printf("\tPublic exponent: %d\n", pubKey.E)
    70  	log.Printf("\tModulus: (%d bits) %X\n", pubKey.N.BitLen(), pubKey.N.Bytes())
    71  	return pubKey, nil
    72  }
    73  
    74  // rsaGenerate is used to generate and verify a RSA key pair of the size
    75  // specified by modulusLen and with the exponent 65537.
    76  // It returns the public part of the generated key pair as a rsa.PublicKey
    77  // and the random key ID that the HSM uses to identify the key pair.
    78  func rsaGenerate(session *pkcs11helpers.Session, label string, modulusLen uint) (*rsa.PublicKey, []byte, error) {
    79  	keyID := make([]byte, 4)
    80  	_, err := newRandReader(session).Read(keyID)
    81  	if err != nil {
    82  		return nil, nil, err
    83  	}
    84  	log.Printf("Generating RSA key with %d bit modulus and public exponent %d and ID %x\n", modulusLen, rsaExp, keyID)
    85  	args := rsaArgs(label, modulusLen, rsaExp, keyID)
    86  	pub, _, err := session.GenerateKeyPair(args.mechanism, args.publicAttrs, args.privateAttrs)
    87  	if err != nil {
    88  		return nil, nil, err
    89  	}
    90  	log.Println("Key generated")
    91  	log.Println("Extracting public key")
    92  	pk, err := rsaPub(session, pub, modulusLen, rsaExp)
    93  	if err != nil {
    94  		return nil, nil, err
    95  	}
    96  	log.Println("Extracted public key")
    97  	return pk, keyID, nil
    98  }
    99  

View as plain text