diff --git a/cmd/ceremony/main.go b/cmd/ceremony/main.go
index 97c94eb1d..629a24a24 100644
--- a/cmd/ceremony/main.go
+++ b/cmd/ceremony/main.go
@@ -98,6 +98,7 @@ type keyGenConfig struct {
 	Type         string `yaml:"type"`
 	RSAModLength int    `yaml:"rsa-mod-length"`
 	ECDSACurve   string `yaml:"ecdsa-curve"`
+	Extractable  bool   `yaml:"extractable"`
 }
 
 var allowedCurves = map[string]bool{
@@ -173,6 +174,7 @@ type rootConfig struct {
 	} `yaml:"outputs"`
 	CertProfile certProfile `yaml:"certificate-profile"`
 	SkipLints   []string    `yaml:"skip-lints"`
+	Renewal     bool        `yaml:"renewal"`
 }
 
 func (rc rootConfig) validate() error {
@@ -188,9 +190,11 @@ func (rc rootConfig) validate() error {
 	}
 
 	// Output fields
-	err = checkOutputFile(rc.Outputs.PublicKeyPath, "public-key-path")
-	if err != nil {
-		return err
+	if !rc.Renewal {
+		err = checkOutputFile(rc.Outputs.PublicKeyPath, "public-key-path")
+		if err != nil {
+			return err
+		}
 	}
 	err = checkOutputFile(rc.Outputs.CertificatePath, "certificate-path")
 	if err != nil {
@@ -576,23 +580,42 @@ func rootCeremony(configBytes []byte) error {
 		return fmt.Errorf("failed to setup session and PKCS#11 context for slot %d: %s", config.PKCS11.StoreSlot, err)
 	}
 	log.Printf("Opened PKCS#11 session for slot %d\n", config.PKCS11.StoreSlot)
-	keyInfo, err := generateKey(session, config.PKCS11.StoreLabel, config.Outputs.PublicKeyPath, config.Key)
-	if err != nil {
-		return err
+	var rKeyInfo *keyInfo
+	if config.Renewal {
+		// Reuse existing root key for a renewal
+		pub, _, err := loadPubKey(config.Outputs.PublicKeyPath)
+		if err != nil {
+			return err
+		}
+
+		der, err := x509.MarshalPKIXPublicKey(pub)
+		if err != nil {
+			return fmt.Errorf("Failed to marshal public key: %s", err)
+		}
+
+		rKeyInfo = &keyInfo{
+			key: pub,
+			der: der,
+		}
+	} else {
+		rKeyInfo, err = generateKey(session, config.PKCS11.StoreLabel, config.Outputs.PublicKeyPath, config.Key)
+		if err != nil {
+			return err
+		}
 	}
-	signer, err := session.NewSigner(config.PKCS11.StoreLabel, keyInfo.key)
+	signer, err := session.NewSigner(config.PKCS11.StoreLabel, rKeyInfo.key)
 	if err != nil {
 		return fmt.Errorf("failed to retrieve signer: %s", err)
 	}
-	template, err := makeTemplate(newRandReader(session), &config.CertProfile, keyInfo.der, nil, rootCert)
+	template, err := makeTemplate(newRandReader(session), &config.CertProfile, rKeyInfo.der, nil, rootCert)
 	if err != nil {
 		return fmt.Errorf("failed to create certificate profile: %s", err)
 	}
-	lintCert, err := issueLintCertAndPerformLinting(template, template, keyInfo.key, signer, config.SkipLints)
+	lintCert, err := issueLintCertAndPerformLinting(template, template, rKeyInfo.key, signer, config.SkipLints)
 	if err != nil {
 		return err
 	}
-	finalCert, err := signAndWriteCert(template, template, lintCert, keyInfo.key, signer, config.Outputs.CertificatePath)
+	finalCert, err := signAndWriteCert(template, template, lintCert, rKeyInfo.key, signer, config.Outputs.CertificatePath)
 	if err != nil {
 		return err
 	}
